- PVSM.RU - https://www.pvsm.ru -
Сервисы падали, падают и будут падать
Когда вы быстро растете, микросервисы начинают появляться буквально по щелчку пальцев и в самых неожиданных местах. В таких условиях каждая команда обычно на ходу решает, где, как и какие логи будет складывать. Когда сначала 10, потом 20, а там и более команд логируют по-своему, начинается хаос.
Например, наша команда сопровождения маркетинга в Skyeng знала: пользователь с таким-то айдишником нажал в личном кабинете кнопку «Сменить преподавателя» — постучался в наш сервис, дальше ушло три сообщения, в очереди было 2 вызова сервисов и эти сервисы ответили 200. Но на самом деле, что было у команд сопровождения учителей или биллинга, к которым мы стучались, не знал никто…
В компании есть стандарт окружения: PHP 7.x, Symfony 4.x, RabbitMQ для системы сообщений, GuzzleHTTP для внешних и своих ip, Docker. Благодаря тому, что нам более-менее известно, что будет в каждой команде, мы написали библиотеку, которая помогла бы сделать трассировку запроса по всей системе с первого клика.
У нас два основных транспорта – HTTP и RabbitMQ. Запрос приходит или от пользователя, или по cron.
Дальше прокидываем request-id всем следующим получателям в нашем облаке:
Opentracing, маркировка через request-id и складывание в правильные места – первые шаги к тому, чтобы в компании появились хорошие логи. Когда команды подключат нашу библиотеку, схема выше начнет работать: request-id начнет передаваться по HTTP и AMQP, каждый сервис будет знать, в рамках какого глобального запроса он сейчас работает. И мы увидим, как запросы расползаются по нашей инфраструктуре.
Мы посчитали, что делая сложную композицию из нескольких классов, логер не нужно вставлять в конструктор. Он должен находиться сбоку и подключаться де-факто. В Java для этого, например, есть SLF4J аннотация.
В PHP нет таких аннотаций, поэтому многие прокидывают в конструктор логеры, как дополнительную зависимость. Нам не нравился такой подход, поэтому мы сделали trait, который служит почти как аннотация (т.к. мы используем Symfony, то trait опирается на функционал autowiring — в результате получается практически как в Java).
Что мы логируем? Помимо request-id, это:
Также есть вещи, которые можно записать заранее: запуск контроллера, запуск консьюмера. Можно заранее проставить уровень debug — он не будет попадать никуда, но если нужно, сможете включить на тестинге или на проде, посмотреть, что у вас происходит — вплоть до запросов в базу.
На приложения у нас заводится New Relic, но мы дополнительно остановились на разделении записей между Sentry и Kibana.
В Sentry падает то, что требует немедленной реакции. Мы заходим в отдельный проект, видим, сколько событий конкретного типа ошибок. Так как в Sentry летит только то, что надо исправлять, тут нет оверхеда, пока у нас не появляется куча ошибок.
Наша панелька с «небоскребами» — если они растут, значит, кто-то сегодня закончит работу попозже.
Если ткнуть глубже, видно, какие пользователи были затронуты, графики, какой браузер, теги, версия PHP — статистики очень много. Плюс можно сразу сделать таску в Jira из ошибки, настроить алерты, назначить ответственных, которым придет оповещение.
Самое главное — не класть ошибки, которые вы не собираетесь править. Например, access denied сюда не летит.
Но в Sentry есть и свой минус – он не очень хорошо справляется с большим потоком. Если вы, например, поделили на 0 и выкатили в прод, хранилище может лечь. Плюс надо помнить о том, что ошибка в одном сервисе может породить вал ошибок в другом сервисе. Решение этой проблемы выходит за тему статьи, но в целом смотрите в сторону паттерна circuit breaker [1].
Лог всего, что не ошибки, мы прокидываем как JSON в Kibana. Для этого сборщик Beats ходит, собирает файлы, наш модуль для Filebeat отправляет их в Elasticsearch, а дальше мы уже в Kibana все вычитываем. Правильнее было бы вычитывать логи с вывода контейнера — и местами мы так и делаем.
Наша Kibana… Выглядит она как Kibana — хороший полнотекстовый поиск, свой язык запросов, всякие поля.
Хранится все: лог действий пользователя в контроллерах, начало и конец запроса в консьюмере, реббитовые запросы, работа бизнес-логики. А сбоку есть Grafana, по ней можно построить разные метрики.
Итак, мы молодцы. Сделали полезную вещь. Что должно было быть результатом этих действий? Все команды начнут использовать единообразные библиотеки как часть ядра. Все, от саппорта до CTO, будут знать, где, как искать и что искать в логах. А единая система алертов сделает жизнь еще прекраснее… Внедряем? Да, но есть нюанс.
Зато понимающие люди будут говорить: «Он внедрил логи по всей компании»
Внедрение — это не про технологии и код. А про политику. Ситуация, когда одна из команд сделала что-то, что неплохо-было-бы затащить к себе и другим, встречается часто. Но у других уже планы и приоритеты на месяцы вперед. У нас тут демократия — кроме критичных вещей вроде единого окружения никто никому ничего не навязывает.
Чтобы логи стали единообразными, их идею надо «продать». Вот какую многоходовочку соорудили мы.
Шаг 0. Начните с себя. Чтобы показать другим, как это классно, легко и красиво, вам нужно тестовое внедрение. Мы начали с собственной команды — в маркетинге как раз было около 20 сервисов. Заодно поняли, какие вопросы и сложности скорее всего возникнут — и начали готовиться к ним.
Шаг 1. Вы идете к CTO и тимлидам. Вы думаете на языке PHP, они — уже бизнесом, фичами, деньгами. Аргументируйте на их языке:
Шаг 2. Ок, зашли к начальству и возбудили его. Теперь приходим к командам. Их первая и естественная реакция — тебя послать, потому что ты вроде как принес им дополнительной работы, а начальство теперь «может спрашивать про логи».
Да, часть рабочего времени в ближайшие месяцы вы все равно будете просто ходить по командам, спрашивать «А как оно там?», делать ревью внедрения и так далее. Но поверьте, оно того стоит.
p.s. Пост основан на опыте и рассказах Вани, Макса и Димы, которые вместе делали этот проект. Мы не придумали, от чьего аккаунта это публиковать, и залили от аккаунта компании. В комментариях ребята готовы ответить от своих аккаунтов.
p.p.s. В посте использованы цитаты из докладов Макса [2] и Вани [3] про этот проект.
Автор: Edtech на удаленке
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/360842
Ссылки в тексте:
[1] circuit breaker: https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern
[2] Макса: https://youtu.be/9NpwwNOvbj4
[3] Вани: https://youtu.be/1pd2XzCjlfg
[4] Источник: https://habr.com/ru/post/531858/?utm_source=habrahabr&utm_medium=rss&utm_campaign=531858
Нажмите здесь для печати.