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

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

Еще одно преимущество от знания тенденций проявляется при планировании объемов. Достигли ли мы их пределов? Сколько еще можно проработать до возникновения потребностей в дополнительных хостах? В прошлом, когда мы ставили физические хосты, эта работа зачастую носила ежегодный характер. В новые времена, когда вычислительные мощности предоставляются поставщиками инфраструктур как служб (IaaS) по требованию, мы можем расширять и сужать возможности системы за считаные минуты, если не секунды. Значит, если мы разбираемся в своих схемах использования, то можем удостовериться в том, что в нашем распоряжении имеется достаточно элементов инфраструктуры для удовлетворения текущих потребностей. Чем интеллектуальнее подход к отслеживанию тенденций и пониманию того, как на них реагировать, тем более экономически оправданной и отзывчивой может стать наша система.

Рабочие показатели сервисов

Операционные системы, под которыми мы работаем, генерируют большое количество показателей, в чем можно убедиться, найдя время для установки на Linux-машине такого средства, как collectd, и указания на него в Graphite. Такие вспомогательные подсистемы, как Nginx или Varnish, также раскрывают весьма полезную информацию, например показатели времени откликов или попаданий в кэш-память. Ну а как насчет вашего собственного сервиса?

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

Зачем все это нужно? По целому ряду причин. Во-первых, существует довольно старое поверье, что 80 % возможностей программных средств никогда не используются. Сейчас я не берусь комментировать его точность, но как человек, создающий программные средства почти 20 лет, я знаю, что потратил много времени на разработку возможностей, которые фактически не находили применения. Разве не хочется вам узнать о том, что это за возможности?

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

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

Для различных платформ существуют библиотеки, позволяющие сервисам отправлять показатели стандартным системам. Одним из примеров такой библиотеки для JVM может послужить Codahale Metrics. Она позволяет сохранять показатели в виде счетчиков, таймеров или измерений, поддерживать показатели за определенный период времени (можно указать показатели вроде «количество заказов за последние пять минут»), а также выходить во внешнюю среду за счет поддержки отправки данных средству Graphite и другим системам объединения данных и создания отчетов.

Искусственный мониторинг

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

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

Впервые я сделал это в далеком 2005 году. Тогда я входил в небольшую команду ThoughtWorks, создававшую систему для инвестиционного банка. За торговый день происходила масса событий, оказывающих влияние на рынок. Наша задача заключалась в реагировании на эти изменения и отслеживании их влияния на портфолио банка. Работа велась в условиях постановки жестких сроков готовности, и целью было вместить все наши вычисления менее чем в десять секунд после наступления события. Система состояла из пяти отдельных сервисов, из которых минимум один был запущен на вычислительной grid-архитектуре, которая, помимо прочего, забирала неиспользуемые циклы центральных процессоров у примерно 250 хостов на базе настольных систем в пользу банковского центра восстановления после аварий.

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

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

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

Реализация семантического мониторинга

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

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

Разумеется, нам нужно сделать кое-что еще. Во-первых, позаботиться о требованиях, предъявляемых к данным наших тестов. Может понадобиться найти способ, позволяющий приспособить тесты к различным актуальным данным, если они со временем изменяются, или же установить разные источники данных. Например, у нас может быть набор фиктивных пользователей, задействованных в производственном режиме с заранее известным набором данных.

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

Идентификаторы взаимосвязанности

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