Повышение производительности монолитной системы - это не меньше, чем попытка переместить гору с одного места на другое. Вещи настолько тесно связаны друг с другом, что становится сложно вносить какие-либо изменения. В отличие от микросервисов, где все полностью контролируется несколькими людьми, здесь все делятся друг с другом.

В последнее время я потратил много времени на улучшение производительности компонента в монолитном приложении. И постепенно мне удалось улучшить производительность более чем на 40%. Поэтому я хотел бы поделиться своим опытом с точки зрения производительности, поскольку это может быть полезно, если ваша система движется в сторону монолита или если вы пытаетесь улучшить производительность уже существующей монолитной системы.

Во-первых, позвольте мне перечислить проблемы, с которыми сталкивается монолитная система, по сравнению с моим предыдущим опытом работы с системой на основе SOA / микросервисов.

Проблемы

Отсутствие собственности

Со временем все меняется, и люди переходят из одной команды в другую или в другую компанию. Теперь в монолите кодовая база является общей, и со временем может случиться так, что определенная часть кода станет бесхозной. Не будет никого, кто бы владел этим фрагментом кода. Так что, если у кого-то есть проблемы с этим компонентом, он должен понять и улучшить его. Это не оптимально, поскольку человек, решающий проблему, не имеет в ней опыта, возможно, он не учел время, чтобы решить эту проблему. И после исправления они тоже пойдут дальше. Я сталкивался с этим несколько раз при поиске команды, владеющей каким-либо модулем, используя слияние, историю коммитов, слабые каналы и т. Д.

Нет определенного SLA

Часто может случиться так, что будет команда, которая будет работать над каким-либо компонентом кода, но поскольку нет четкого разделения служб, нет соблюдения каких-либо контрактов или SLA. В большинстве случаев вы будете строить графики для других сервисов, чтобы определить время их отклика, и они не обязаны его придерживаться, поскольку они не определяют и не контролируют SLA.

Трудно найти регресс

Поскольку нет разделения служб, очень сложно выяснить основную причину, когда производительность вашего компонента начинает ухудшаться. Вы посмотрите на код внизу, и, поскольку нет демаркации границ, вы не сможете легко выделить проблемную область. Даже инфраструктура является общей, поэтому вы не можете сказать, кто мог ее испортить. Вам придется провести большое расследование, чтобы выяснить, кто что изменил в последние дни, что могло стать причиной этого. Возможно, вам придется посмотреть на несколько других проблем, возникающих в вашем приложении, и посмотреть, есть ли у вас что-то общее, а затем присоединиться к ним.

Отсутствие контроля над базовой инфраструктурой

Поскольку все используют одну и ту же базовую инфраструктуру, довольно легко, что кто-то другой может начать потреблять больше ресурсов, таких как потоки, соединения с БД, циклы ЦП, память и т. Д., И у вас нет большой информации и контроля над этим. То же самое можете сделать вы с другими. Поэтому становится довольно сложно определить или оптимизировать роль инфраструктуры в ваших задачах производительности.

Области улучшения

Как мы видели выше, существует множество трудностей в управлении и улучшении производительности монолита, но все же мы должны поддерживать его и улучшать или поддерживать производительность. Разделение монолита на сервисы - один из основных архитектурных шагов, которые вы можете сделать, однако это требует времени и совместной работы множества людей. В этом блоге я хотел бы больше сосредоточиться на коде и методах, которые вы должны изучить, которые, как я считаю, являются ключевыми принципами и довольно распространены для монолитов и приносят вам пользу.

Исключения

Часто API продолжает накапливать все больше и больше данных с новыми требованиями. Со временем некоторые из этих запросов могут устареть, поэтому их следует очистить, если они не требуются, поскольку они могут быть дорогостоящими, но все же использоваться. Когда мы пересмотрели наш API, мы обнаружили, что значительная часть информации не использовалась клиентской частью, и исключение этих частей дало нам выигрыш примерно на 10–15%.

Параллелизм

Если задачи сопоставимы по характеру и производительности, это может помочь выполнять их параллельно. Вы должны быть осторожны, так как если задачи разделены слишком маленькими, это может быть неэффективным. А поскольку это обычная инфра-информация, вывести это довольно сложно. В наших случаях, когда мы распараллелили немного более длинные задачи, мы получили выигрыш, но со слишком большим количеством более мелких задач это не повлияло.

Определите основные узкие места

В нашем случае, несмотря на то, что API делал слишком много, в результате глубокого анализа мы выяснили, что существует серьезное узкое место. Если вы решите одно большое узкое место, это принесет вам больше пользы, чем решение кусочков здесь и там. И да, вместо того, чтобы решать все, что вам нужно, наймите правильную команду. Они могут решить эту проблему лучше и быстрее, поскольку у них больше опыта в этом.

Удалить избыточные вызовы

Если одно и то же выполняется в нескольких местах снова и снова во время выполнения API, что является очень нормальным сценарием в монолите, в зависимости от контекста того, как он используется, он может быть извлечен в обычное место и может быть выполнен. только один раз. Например, для любого ресурса, если необходимо выполнить какую-либо проверку разрешений, это можно сделать только один раз, а затем вы должны выбрать версию, которая пропускает проверки разрешений во время последующей обработки.

Использовать кеш уровня запроса

В монолите, поскольку в одном запросе так много вызовов, а идентификаторы передаются для общих сущностей, они обычно вызываются несколько раз. Как я уже говорил выше, оптимально вызывать каждый метод только один раз в потоке выполнения. Однако иногда это может быть невозможно. Если один и тот же метод вызывается несколько раз в запросе и значительно увеличивает общую задержку, вам следует использовать Кэш области запроса, который кэширует результат первого вызова во время выполнения, использует сохраненные приводит к последующим вызовам и делает его недействительным в конце запроса.

Заключение

Управление производительностью монолита и ее улучшение - сложная и сложная задача. Однако, чтобы лучше управлять этим, «Измеряйте все регулярно». Иногда на то, что может показаться проще, требуется время. Используйте в коде некоторые инструменты, такие как профилировщик или таймеры, в качестве контрольных точек, чтобы вы могли не только оценить их время, но и определить причину, если что-то не работает. И самое главное - постоянно проверять архитектуру, чтобы поддерживать систему в управляемом состоянии.