Portal
Где находятся потенциальные bottleneck'и? Будущие улучшения

Где находятся потенциальные bottleneck'и? Будущие улучшения

Когда система только создаётся, её главная проблема обычно не в производительности.

Главная задача на этом этапе — чтобы система просто корректно работала: приходит request, backend его обрабатывает, получает данные из database и возвращает ответ.

Но по мере роста системы ситуация меняется.

Увеличивается количество пользователей, одновременно приходит всё больше request'ов, database получает больше запросов, появляются зависимости от сторонних сервисов — и некоторые части системы, которые раньше вообще не были заметны, начинают определять её общую скорость.

Именно здесь появляется понятие bottleneck.

Bottleneck — это самая медленная или наиболее нагруженная часть системы. И самое интересное, что bottleneck далеко не всегда находится там, где мы ожидаем.

Иногда проблема не в CPU, а в database connection pool. Иногда проблема не в самой database, а в том, что несколько сервисов одновременно записывают данные в одну и ту же таблицу. А иногда вся система работает очень быстро, но внешний API отвечает за 2 секунды — и именно это пользователь воспринимает как задержку.

Поэтому при планировании будущих улучшений недостаточно просто сказать: «Давайте увеличим мощность сервера».

1. Database — один из главных кандидатов

В backend-системах database — один из наиболее распространённых bottleneck'ов.

На начальном этапе, например, для одного request может быть достаточно 2–3 SQL-запросов. Но по мере роста системы этот endpoint начинают использовать всё чаще, и нагрузка на database быстро увеличивается.

100 request'ов/секунду × 5 SQL-запросов = 500 запросов к database в секунду

Если один из этих запросов содержит тяжёлый JOIN, большой table scan или выполняется без подходящего index, проблема уже находится не на application server.

Первым шагом здесь не должно быть замены database.

Сначала нужно:

  • определить slow query;

  • проанализировать execution plan;

  • уменьшить количество ненужных query;

  • оптимизировать index'ы;

  • правильно настроить connection pool;

  • внедрить pagination;

  • не допускать повторного чтения одних и тех же данных из database.

Особенно в microservice-системах с shared database нагрузка, создаваемая одним сервисом, может влиять и на другие сервисы. AWS также обращает внимание на такие риски shared-database подхода, как hot tables и runtime coupling между сервисами.

2. Читать всё из database без cache

Ещё одним потенциальным bottleneck'ом является ситуация, когда часто используемые данные каждый раз запрашиваются из database.

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

В такой ситуации вместо того, чтобы отправлять каждый request в database, может быть гораздо логичнее использовать cache.

До: database обрабатывает каждый request.

После: cache берёт на себя большую часть нагрузки по чтению из database.

Cache обычно располагается между application server и database, чтобы уменьшить нагрузку на database при чтении и улучшить latency.

Для этого хорошо подходит и cache-aside подход: сначала проверяем cache, и только при cache miss обращаемся к database.

3. Synchronous communication в будущем может стать причиной задержек

В microservice-архитектуре ещё одним потенциальным bottleneck'ом является communication между сервисами.

Client → Order Service → Customer Service → Payment Service → Notification Service

На первый взгляд здесь нет ничего проблемного.

Но если Order Service должен дождаться ответа от всех сервисов перед тем, как вернуть response клиенту, то самый медленный сервис начинает определять скорость выполнения всего request.

  • Customer Service → 50 ms

  • Payment Service → 100 ms

  • Notification Service → 800 ms

В результате операция в Notification Service, которая занимает 800 ms, заставляет пользователя ждать завершения всего request.

Хотя на самом деле Notification Service может вообще не требоваться для того, чтобы вернуть response пользователю.

В таких случаях часть операций можно перевести на asynchronous processing.

4. Connection pool тоже может стать bottleneck'ом

Иногда CPU application server загружен всего на 30%, memory находится в норме, database тоже выглядит нормально.

Но request'ы всё равно ждут.

Причиной может быть connection pool.

Например, application может иметь всего 20 database connection, в то время как 200 request'ов одновременно пытаются обратиться к database.

CPU сервера при этом может практически простаивать, но если request'ы ждут свободное connection, система всё равно будет работать медленно.

Именно поэтому анализ bottleneck'ов нельзя сводить исключительно к теме «slow query в database». В production реальная причина задержки может находиться совершенно в другом месте.

5. Внешние сервисы находятся не под нашим контролем

Ещё один интересный bottleneck в production-системах — это внешние зависимости.

Our Backend → Payment API, SMS Provider, Email Provider, External API

Наше application может обработать запрос за 50 ms.

Но если external API отвечает через 1,5 секунды, пользователь всё равно будет воспринимать это как медленную работу нашей системы.

The slowest dependency can define the user experience.

То есть самый медленный dependency может фактически определять пользовательский опыт.

Поэтому для внешних зависимостей особенно важны timeout'ы, retry-политики, circuit breaker'ы и возможность не блокировать основной request там, где это не требуется.

6. Когда одной database уже недостаточно

По мере роста системы может возникнуть необходимость распределить нагрузку database.

Здесь цель не просто в том, чтобы сделать database мощнее.

Цель — отделить read workload от write path.

Например, для этого можно использовать read replica, чтобы перенести часть нагрузки по чтению с основной database.

Такой подход позволяет не заставлять одну database одновременно обрабатывать весь read и write workload.

7. Самое важное улучшение: видеть bottleneck заранее

На самом деле самое важное будущее улучшение — это не выбор какой-то конкретной технологии.

Главное — иметь возможность измерять, где именно система начинает замедляться.

Именно поэтому так важна observability.

Если request выполняется 900 ms, главный вопрос не «Он медленный?».

Главный вопрос — «Почему?»

Например:

  • 620 ms — database

  • 180 ms — external API

  • 90 ms — connection

  • остальное — application logic?

Именно для этого используется distributed tracing — чтобы видеть, сколько времени request проводит в разных сервисах и компонентах системы.

Monitoring, centralized logging и distributed tracing являются ключевыми составляющими observability в microservice-архитектуре.

Заключение

Bottleneck системы сегодня может находиться в database, а завтра database уже может перестать быть проблемой.

По мере роста количества пользователей проблема может переместиться в application server, connection pool, network, queue или external dependency.

Поэтому будущие улучшения правильнее планировать примерно так:

Measure → Identify → Optimize → Scale

Сначала измерь.

Потом найди, где именно находится проблема.

После этого оптимизируй конкретную проблемную часть.

И только затем, если это действительно необходимо, переходи к horizontal scaling, caching, queue, read replica, sharding или более сложным архитектурным решениям.

Хорошая архитектура — это не та архитектура, в которой используется как можно больше технологий.

Хорошая архитектура — это та, в которой ты можешь увидеть, где возникла проблема, и решить её с необходимым, а не избыточным уровнем сложности.

Именно отсюда вытекают основные направления будущих улучшений этой системы:

database optimization → caching → asynchronous processing → connection pool tuning → dependency isolation → observability

Не нужно внедрять всё это только потому, что «в будущем система станет большой».

По мере роста системы именно метрики покажут нам, где находится следующий bottleneck.

И в этом, по сути, заключается одна из главных целей хорошего engineering:

Не усложнять систему заранее без необходимости, а тогда, когда появляется реальная потребность, правильно масштабировать именно то место, которое этого требует.

Другие статьи можно посмотреть здесь:

https://aladdinbiyabangerd.site/ru/writing

Нравится эта статья

Нравится 0 людям понравилось

Поделиться статьёй

1 человек прочитал эту статью

Готовы начать учиться? Смотреть карьерные пути
Напишите нам в WhatsApp