Создание микросервисов — страница 44 из 69

Когда работа ведется с монолитным приложением, по крайней мере есть на что свалить вину. Сайт замедлился? Виноват монолит. Сайт выдает странные ошибки? И в этом тоже он виноват. Центральный процессор загружен на все 100 %? Это монолит. Запах дыма? Ну вы уже поняли. Наличие единого источника всех бед отчасти упрощает расследование причин!

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

Теперь у нас есть несколько отслеживаемых серверов, несколько регистрационных файлов, которые нужно будет переворошить, и множество мест, где сетевые задержки могут вызвать проблемы. И как ко всему этому подступиться? Нужно понять, что может стать причиной хаоса и путаницы, с которыми не хотелось бы столкнуться в пятничный полдень (да и в любое другое время!).

На все это есть довольно простой ответ: нужно отслеживать небольшие области, а для получения более общей картины использовать объединение. Чтобы посмотреть, как это делается, начнем с самого простого из возможного — с отдельного узла.

Один сервис на одном сервере

На рис. 8.1 представлена весьма простая установка: на одном хосте запущен один сервис. Теперь нам нужно проводить его мониторинг, чтобы быть в курсе, если что-то пойдет не так, и иметь возможность все исправить. Итак, что именно мы должны отслеживать?

Рис. 8.1. Один сервис на одном хосте


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

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

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

Время не стоит на месте, нагрузка растет, и появляется необходимость в расширении…

Один сервис на нескольких серверах

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

Будет ли при высокой загруженности центрального процессора, от которой не застрахован ни один из хостов, что-либо указывать на проблему в самом сервисе, или же признак этого будет изолирован на самом хосте, указывая на то, что проблема касается именно его и, возможно, связана с нештатным поведением процесса операционной системы?

Рис. 8.2. Один сервис, распределенный по нескольким хостам


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

Теперь о журналах. Поскольку сервис запущен на более чем одном сервере, нам, чтобы заглянуть вовнутрь, придется, наверное, регистрироваться на каждом из них. Если количество хостов невелико, можно воспользоваться таким средством, как SSH-мультиплексор, которое позволяет запускать одни и те же команды сразу на нескольких хостах. Затем понадобятся большой монитор и поиск виновника с помощью команды grep "Error" app.log.

Для задач типа отслеживания времени отклика мы можем, не проводя специального объединения, довольствоваться отслеживанием балансировщика нагрузки. Но нужно, разумеется, отслеживать работу и самого балансировщика: если он начнет барахлить, у нас возникнут проблемы. Тут, наверное, нужно побеспокоиться и о том, как должен выглядеть нормально работающий сервис, поскольку мы будем настраивать балансировщик нагрузки на удаление из приложения неисправных узлов. Надеюсь, что, дойдя до этого места, мы уже сможем выдать несколько идей на сей счет…

Несколько сервисов на нескольких серверах

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

Рис. 8.3. Несколько совместно работающих сервисов, распределенных по нескольким хостам


Ответом могут стать сбор и централизованное объединение всего, до чего только могут дотянуться наши руки: от регистрационных журналов до показателей приложений.

Журналы, журналы и еще журналы…

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

На рис. 8.4 показана система Kibana, построенная на движке ElasticSearch и предназначенная для просмотра журналов. Для поиска по журналам можно воспользоваться синтаксисом запросов, позволяющим ограничивать диапазоны времени и дат или использовать регулярные выражения для поиска соответствующих им строк. Kibana может даже генерировать из журналов диаграммы и отправлять их в ваш адрес, позволяя вам, к примеру, с первого взгляда замечать количество ошибок, зарегистрированных за определенное время.

Рис. 8.4. Использование Kibana для просмотра объединенных журналов


Отслеживание показателей сразу нескольких сервисов

Наряду с решением сложностей с просмотром журналов различных хостов нам нужно подыскать наилучшие способы для сбора и просмотра показателей. При рассмотрении показателей более сложных систем может быть трудно узнать, как именно выглядят приемлемые параметры. На нашем сайте замечено около 50 HTTP-ошибок в секунду с кодами 4XX. Плохо ли это? Загруженность центрального процессора сервисом каталогов увеличилась в обеденное время на 20 % — это нормально? Секрет осведомленности о том, когда следует поднимать тревогу, а когда можно расслабиться, кроется в сборе показателей о поведении системы за период времени, достаточно длительный для того, чтобы могла проявится четкая схема.

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

Graphite — одна из таких систем, способная существенно упростить решение данной задачи. Она предоставляет очень простой API-интерфейс и позволяет вам отправлять показатели в реальном времени. Затем она позволяет запрашивать эти показатели для создания диаграмм и других наглядных представлений для оценки ситуации. Представляет интерес способ, используемый этим средством для обработки объема данных. Фактически оно настраивается так, чтобы снизить анализ более старых показателей, гарантируя тем самым, что объем не станет разрастаться слишком сильно. Так, к примеру, можно делать одну запись показателей центрального процессора для хостов каждые десять секунд за последние десять минут, затем для каждого последнего дня делать объединенный показатель каждую минуту, опускаясь, возможно, до одного образца каждые 30 минут за несколько последних лет. Таким образом можно хранить информацию о поведении системы за довольно продолжительный период времени, не нуждаясь в хранилище большого объема.