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

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

Одним из подходов, который может помочь в данной ситуации, является использование идентификаторов взаимосвязанности. Когда делается первый вызов, для него можно сгенерировать глобальный уникальный идентификатор (GUID). Затем (рис. 8.5) он передается по очереди всем последующим вызовам и может быть помещен в ваши журналы в структурированном виде. Это очень похоже на то, что вы уже делали с такими компонентами, как уровень журнала или дата. При правильном применении инструментов объединения журналов после этого появится возможность выполнить трассировку этого события по всей системе:

15-02-2014 16:01:01 Web-Frontend INFO [abc-123] Register

15-02-2014 16:01:02 RegisterService INFO [abc-123] RegisterCustomer…

15-02-2014 16:01:03 PostalSystem INFO [abc-123] SendWelcomePack…

15-02-2014 16:01:03 EmailSystem INFO [abc-123] SendWelcomeEmail…

15-02-2014 16:01:03 PaymentGateway ERROR [abc-123] ValidatePayment…

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

Отследить вызовы, проходящие через несколько системных границ, поможет также такое программное средство, как Zipkin. Основываясь на идеях, заложенных в Dapper — собственной системе отслеживания компании Google, Zipkin может предоставить подробно детализированные результаты отслеживания вызовов между сервисами, а также пользовательский интерфейс, помогающий представить полученные данные. Лично я считаю требования, выдвигаемые Zipkin в плане обычных клиентов и систем сбора данных, несколько тяжеловатыми. При условии, что объединение журналов вам уже требуется для других целей, представляется, что будет намного проще вместо этого воспользоваться уже собранными данными, чем придерживаться обязательств по использованию дополнительных источников данных. Тем не менее, если окажется, что вам для отслеживания подобных межсервисных вызовов нужны более совершенные инструменты, вы можете присмотреться и к ним.

Рис. 8.5. Использование идентификаторов взаимосвязанности для отслеживания цепочек вызовов между несколькими сервисами


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

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

Каскадные сбои

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

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

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

Стандартизация

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

Можно постараться вести записи в журналах в стандартном формате. Вам определенно понадобится содержать все показатели в одном месте, а также использовать перечень стандартных названий показателей, чтобы не допускать весьма раздражающих моментов, когда у одного сервиса будет показатель под названием ResponseTime, а у другого — точно такой же показатель, но названный RspTimeSecs.

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

Расчет на аудиторию

Все данные собирают для вполне определенной цели. Точнее, мы проводим сбор всех этих данных для разных людей, чтобы помочь им справиться с поставленными перед ними задачами. Эти данные побуждают к действию. Часть данных нужна как сигнал к незамедлительному побуждению к действию нашей команды поддержки, например, в случае, когда не проходит один из тестов искусственного мониторинга. Другая часть данных, наподобие того факта, что нагрузка на центральный процессор увеличилась по сравнению с прошлой неделей на 2 %, потенциально представляет интерес, только если мы выполняем планирование использования ресурсов. Возможно также, что ваш начальник хочет немедленно узнать о том, что после последнего выпуска выручка упала на 25 %, но, скорее всего, волноваться не о чем, так как за последний час поиск по ключевым словам Justin Bieber возрос на 5 %.

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

• о чем они хотят знать в текущий момент;

• что им может понадобиться чуть позже;

• как они хотят воспользоваться данными.

Оповещайте о том, что они должны знать прямо сейчас. Создайте большое окно с данной информацией, располагающееся в углу экрана. Предоставьте легкий доступ к данным, о которых они хотят узнать чуть позже. И уделите время общению с ними, чтобы узнать, как они хотят воспользоваться данными. Обсуждение всех нюансов графического отображения количественной информации, конечно же, выходит за рамки данной книги, но для начала отличным подспорьем может послужить прекрасная книга Стивена Фью (Stephen Few) Information Dashboard Design: Displaying Data for Ata-Glance Monitoring (Analytics Press).

Перспективы

Мне известно множество организаций, в которых показатели разбросаны по разным системам. Показатели на