Микросервисы дают нам как разработчикам невероятное количество свободы. Мы можем выбрать наш язык и решить, где и когда развернуть наш сервис. Однако одной из самых больших проблем с микросервисами является выяснение того, как все идет не так. С помощью микросервисов мы можем создавать большие распределенные приложения, но это также означает, что поиск неисправностей является сложной задачей. Еще сложнее отследить ошибки, когда вы используете платформу типа AWS Lambda.
Как хорошие разработчики, мы пишем наши модульные тесты и интеграционные тесты, и мы гарантируем, что все эти тесты пройдут. Вместе с командой обеспечения качества мы пишем сложные тестовые сценарии, чтобы убедиться, что наш код ведет себя так, как мы планировали. Однако мы никогда не можем предсказать, как наши конечные пользователи будут использовать программное обеспечение. Всегда есть новые проблемы, о которых мы не думали. Вот почему полезны инструменты мониторинга приложений, такие как Sentry.io. Эти события могут быть ошибками, но они также могут быть другими типами событий.
По мере того, как приложения растут и становятся все более сложными, время, которое требуется, чтобы выяснить, где что-то идет не так, также увеличивается. По мере того, как вы перестраиваете приложения для управления событиями и используете серверные вычисления, эта сложность будет увеличиваться еще больше. ACME Fitness Shop — одно из приложений, созданных нами для демонстрации того, над чем мы работаем в команде . ACME Fitness Shop состоит из шести микросервисов, каждый из которых работает в своих собственных контейнерах и использует свои собственные хранилища данных.
В течение последних месяцев команда CloudJourney.io работала над безсерверной версией ACME Fitness Shop. В настоящее время безсерверная версия имеет 24 лямбда-функции, которые работают вместе. Отслеживать, что они все делают и где все рушится, очень сложно. Вместо того, чтобы иметь один контейнер, который выполняет всю «работу с корзиной», теперь есть восемь различных функций Lambda.
Лямбда-функции на приведенной выше диаграмме выполняют те же функции, что и их контейнерные аналоги на первом изображении. Фактически, вы можете поменять сервисы на основе контейнеров на бессерверные сервисы и никогда не почувствовать разницу.
Хотя у нас могут быть разные команды, работающие над разными частями одной и той же группы функциональных возможностей, мы добавили некоторую сложность, когда дело доходит до устранения неполадок и поиска ошибок. Особенно с безсерверным, вы не можете открыть терминальную сессию и «_ssh в контейнер».
Инструментарий Обработка ошибок
Инструментом, который мы выбрали для мониторинга ошибок для этого проекта, был Sentry.io. Для подключения к Sentry единственным требуемым значением является ключ клиента, который Sentry вызывает DSN. Чтобы сохранить это значение в безопасности и обязательно следовать рекомендациям, вы можете сохранить его в хранилище параметров AWS Systems Manager (SSM) и использовать при развертывании приложения с помощью CloudFormation (или SAM).
SSM позволяет создавать иерархические группы для ваших параметров. Используя эту иерархическую функцию, мы назвали параметр /Sentry/Dsn
в SSM. В шаблонах CloudFormation вы можете использовать параметр, например:
HAML
xxxxxxxxxx
1
Parameters:
2
SentryDSN:
3
Type: AWS::SSM::Parameter::Value<String>
4
Default: /Sentry/Dsn
Захват событий
Большинство серверных платформ закрывают все сетевые подключения, как только функция будет завершена, и не будут ждать подтверждения. Чтобы убедиться, что все события получены Sentry, вы можете настроить синхронный HTTP-транспорт. Вместе с несколькими дополнительными настройками соединение с Sentry настраивается следующим образом:
Идти
xxxxxxxxxx
1
sentrySyncTransport := sentry.NewHTTPSyncTransport()
2
sentrySyncTransport.Timeout = time.Second * 3
3
sentry.Init(sentry.ClientOptions{
5
Dsn: os.Getenv("SENTRY_DSN"), // The DSN, coming from the AWS Systems Manager Parameter Store
6
Transport: sentrySyncTransport,
7
ServerName: os.Getenv("FUNCTION_NAME"), // The name of the function so it can be easily found in Sentry's UI
8
Release: os.Getenv("VERSION"), // The version of the deployment so it can be found in GitHub
9
Environment: os.Getenv("STAGE"), // The stage, so you can see if it is test or production
10
})
Sentry предлагает множество полезных событий, которые вы можете отправить, чтобы понять, что происходит в вашем приложении:
- Панировочные сухари : серия событий, произошедших до появления ошибки или сообщения.
- Исключение : произошла ошибка.
- Сообщение : сообщение журнала с дополнительной информацией о событии или ошибке.
В Платежном сервисе данные кредитной карты проверяются, чтобы убедиться, что это действительная кредитная карта. Если у заказа нет действительной кредитной карты, остальная часть потока также будет остановлена, поэтому эту ошибку вы хотите зафиксировать.
Идти
xxxxxxxxxx
1
sentry.CaptureException(fmt.Errorf("validation failed for order [%s] : %s", req.Request.OrderID, err.Error()))
Это ошибка, которую вы обнаружите во время тестирования вашего модуля и интеграции, но, поскольку она сильно влияет на ваш пользовательский опыт, вы, вероятно, захотите отслеживать ее и во время производства.
Возможно и обратное. Если вы хотите захватить успешные вызовы вашего приложения, вы можете сделать это тоже. В этом конкретном случае я бы сказал, что вызов был успешным, когда кредитная карта была успешно проверена, и сообщение было успешно отправлено туда, куда нужно было отправиться (в данном случае очередь SQS). С помощью одного оператора вы можете отправить в Sentry событие, которое фиксирует успех функции Lambda.
Идти
xxxxxxxxxx
1
sentry.CaptureMessage(fmt.Sprintf("validation successful for order [%s]", req.Request.OrderID))
Отслеживание данных
В обоих случаях важно отслеживать дополнительные данные. Эти дополнительные данные могут означать разницу между потерей двух минут на просмотр одного сервиса или потерей целого дня на выяснение того, какие сервисы были затронуты. Панировочные сухари играют здесь важную роль. В этом контексте полезны сумма, номер заказа и сгенерированный идентификатор транзакции.
Эти данные также очень полезны в случае ошибки в службе доставки. Например, когда заказ должен быть отправлен в службу доставки, но никогда не принимается функцией Lambda, вы можете легко отследить, в чем проблема. Добавление этих данных осуществляется через хлебные крошки, например:
Идти
xxxxxxxxxx
1
crumb := sentry.Breadcrumb{
2
Category: "CreditCardValidated",
3
Timestamp: time.Now().Unix(),
4
Level: sentry.LevelInfo,
5
Data: map[string]interface{}{
6
"Amount": req.Request.Total,
7
"OrderID": req.Request.OrderID,
8
"Success": true,
9
"Message": "transaction successful",
10
},
11
}
12
// ...(snip)
14
sentry.AddBreadcrumb(&crumb)
До сих пор мы рассматривали серверные компоненты ACME Fitness Shop. Как уже упоминалось, есть также контейнерная версия, и вы можете смешивать и сочетать части. Именно здесь крайне важно отслеживать и знать, где происходят ошибки.
Вместо того, чтобы просто просматривать журналы в одном месте, вам нужно просматривать журналы как без сервера, так и журналы Kubernetes. В сервисе корзины на основе Python мы также добавили интеграцию Redis. Простое добавление одной строки и оператора import гарантирует, что все выполняемые команды Redis также будут показаны.
питон
xxxxxxxxxx
1
import sentry_sdk
2
from sentry_sdk.integrations.redis import RedisIntegration
3
sentry_sdk.init(
5
dsn='https://<key>@sentry.io/<project>',
6
integrations=[RedisIntegration()]
7
)
Вместо того, чтобы тратить время на выяснение того, где проблема и как определенные данные были переведены в команду Redis, вы можете буквально просто прочитать, что произошло.
По мере того, как ваше приложение переходит от dev к тестированию и к производству, тег среды поможет вам отслеживать, что происходит в какой среде. Проблемы, возникающие в тестовой среде, являются менее актуальными, чем проблемы, возникающие в производстве.
Один из настроенных нами тегов называется «release», который является SHA коммита git. Основываясь на этом, мы можем отслеживать точный коммит, который выполняется в любой среде в любой момент времени, и видеть события, которые были захвачены.
Эти теги, когда привязаны к определенным областям, могут даже позволить вам сопоставлять сообщения вместе. Это дает вам возможность увидеть, что все происходило в вашей системе в момент возникновения ошибки. Некоторые примеры, в том числе трассировку с помощью балансировщика нагрузки Nginx перед вашим приложением, можно найти в документации по Sentry .
Что дальше?
Контейнеры и манифесты Kubernetes для ACME Fitness Shop находятся на GitHub, как и код для ACME Serverless Fitness Shop . Итак, если вы хотите попробовать его и посмотреть, добавляет ли Sentry.io ценность для ваших сценариев использования, вы можете сделать именно это, используя код и приложения, которые мы уже создали. А пока сообщите нам свои мысли и отправьте Биллу , Леону или команде записку в Twitter.