Сравните влияние синхронного и асинхронного журналирования на задержку запроса.
Синхронное журналирование добавляет запись лога в критический путь запроса: обработчик ждёт форматирование и передачу сообщения дальше. Асинхронное журналирование обычно уменьшает задержку и её хвост, потому что запрос передаёт событие в буфер, а отдельный обработчик отправляет его в хранилище позже.
Цена асинхронности — риск переполнения буфера, потери логов и расхождения между моментом успешного ответа и моментом фактической записи события. Поэтому выбор зависит от важности сообщения и допустимой задержки.
Журналирование первоначально выполняли прямо во время обработки запроса, поскольку такой подход прост и сразу сообщает об ошибке вызывающей системе. По мере роста нагрузки стоимость форматирования, блокировок и операций ввода-вывода стала заметной частью времени ответа.
Асинхронная модель появилась как способ отделить выполнение бизнес-операции от медленного вывода логов. Она особенно полезна для диагностических событий, которым не требуется подтверждённая запись до отправки ответа клиенту.
При синхронной записи задержка запроса зависит от журнала, сети, диска и состояния удалённой системы сбора логов. Если это хранилище замедлилось, зависло или стало недоступно, рабочие запросы могут начать ждать его таймаутов.
При асинхронной записи запрос не ждёт полного вывода, но события временно находятся в памяти или локальной очереди. Если скорость поступления логов устойчиво выше скорости отправки, очередь растёт, затем сообщения начинают отбрасываться либо блокировать производителей.
Неверно выбранная политика опасна в обе стороны: синхронная может ухудшить доступность основного сервиса, а асинхронная — скрыть признаки отказа или удалить сведения, необходимые для расследования.
В синхронной схеме обработчик формирует событие и передаёт его логирующему компоненту, после чего продолжает обработку только после принятия сообщения или завершения операции вывода. Поэтому логирование входит в критический путь. Его влияние особенно заметно на p95 и p99, когда редкие задержки внешнего вывода становятся хвостом распределения задержки запроса.
В асинхронной схеме обработчик добавляет событие в ограниченную очередь и продолжает работу. Фоновый потребитель извлекает сообщения, группирует их при необходимости и отправляет в целевую систему. Пока очередь принимает записи достаточно быстро, задержка запроса почти не зависит от скорости внешнего хранилища.
Ключевой параметр — поведение при заполнении очереди. Возможны блокировка производителя, отбрасывание новых событий, отбрасывание старых событий или выборочное сохранение сообщений по приоритету. Универсально лучшего варианта нет: для отладочного сообщения допустима потеря, а для аудита или события безопасности обычно требуется подтверждённое сохранение либо отдельный надёжный канал.
Асинхронность не делает запись надёжной автоматически. До передачи в устойчивое хранилище событие может исчезнуть при завершении процесса, аварии узла или потере содержимого памяти. Для контроля нужны метрики размера очереди, времени ожидания, скорости отбрасывания и ошибок доставки, а также ограничение объёма буфера.
Практическое правило: синхронно фиксируют только те события, без которых нельзя корректно завершить операцию или доказать её результат. Остальные сообщения отправляют асинхронно, но предусматривают ограниченную очередь, явную политику переполнения и механизм сигнализации о потерях.
Сервис оформления заказа начал показывать рост p99 после включения подробного журналирования. Логи отправлялись в удалённую систему синхронно, поэтому кратковременные задержки сети увеличивали время ответа пользовательских запросов.
Рассматривались три варианта. Полное отключение журналирования уменьшало задержку, но лишало команду диагностических данных. Неограниченная асинхронная очередь снижала задержку в штатном режиме, однако создавала риск неконтролируемого потребления памяти. Синхронная запись только критических событий сохраняла надёжность важных сообщений, но не решала проблему диагностических логов.
Выбрали смешанную схему: диагностические события помещали в ограниченную асинхронную очередь, а критические события обрабатывали отдельным надёжным путём. Для очереди добавили метрики заполнения и потерь, а при переполнении сохраняли сообщения высокого приоритета и отбрасывали низкоприоритетные. Это уменьшило влияние журналирования на хвостовую задержку без молчаливой потери всех важных событий.
Нет. Оно уменьшает задержку запроса только пока добавление события в очередь быстро завершается. При блокировке на заполненной очереди, конкуренции за общий буфер или дорогом форматировании до постановки в очередь асинхронная схема также может попасть в критический путь.
Очередь сглаживает кратковременный всплеск, но не устраняет устойчивое превышение скорости поступления над скоростью доставки. В неограниченной очереди это приводит к росту памяти и возможному аварийному завершению процесса. Ограниченная очередь заставляет заранее выбрать компромисс между задержкой основного сервиса, блокировкой производителей и потерей менее важных сообщений.
Нужно сопоставлять число созданных, принятых очередью, отправленных и отброшенных событий, а также измерять возраст самого старого сообщения. Рост очереди, увеличение возраста событий, таймауты доставки и ненулевой счётчик потерь показывают, что наблюдаемость отстаёт или деградирует. Одной метрики успешной работы фонового отправителя недостаточно: он может быть здоров, одновременно не успевая обработать входящий поток.