Привет! Меня зовут Андрей, я возглавляю команду, которая отвечает за надежность и стабильную работу бэкенда в Wrike. Если вы когда-нибудь задумывались, что же такое «backend reliability», то знайте, что вы не один! Я часто объясняю, что это что-то вроде должности инженера по надежности сайта (SRE), но сфокусированная исключительно на бэкенде. В статье я расскажу о зонах ответственности BRE команды и инструментах, которые мы применяем для поддержания стабильной работы бэкенда на высоком уровне. Backend reliability engineer (BRE) — это специалист, который отвечает за устойчивость, стабильность, масштабируемость и производительность серверной части приложения. Это человек, который первым приходит на помощь при возникновении проблем с доступностью или стабильной работой бэкенда. Мы не добавляем в продукт новые функциональности, которые видят пользователи, но если мы не справимся со своими задачами, и приложение не выдержит нагрузку, то пользователи это обязательно заметят. Для бэкенд-инженеров мы предоставляем оптимизированные и надежные решения, которые можно интегрировать в процесс написания кода. Примером таких общих решений являются библиотеки работы с базой, amqp, кешами и другие.  Мы занимаемся разработкой и усовершенствованием общих компонентов системы, которые служат основой для построения приложения: много работаем с базовыми частями системы, упрощая тем самым процесс разработки для всех команд в компании. А еще мы помогаем решать технические проблемы, которые могут возникнуть во время разработки, и помогаем разобраться с инцидентами: например, с повышенным рейтом ошибок по какому-либо эндпоинту или резким увеличением потребления памяти с повышенной нагрузкой на систему.  В нашем арсенале есть большое количество инструментов, которые помогают в работе, и я немного расскажу о том, зачем нам нужен каждый из них. Логирование. Мы хотим, чтобы общие части системы были прозрачными и предоставляли полезную информацию, которую мы сможем использовать при разборе инцидента.  Логирование лучше держать в двух хранилищах: Временное хранилище со всеми сообщениями с хранением в пару недель — этого достаточно для разбора инцидентов или для того, чтобы видеть работу системы здесь и сейчас. Долговременное хранилище, в которое можно писать только важные логи и использовать их для того, чтобы анализировать поведение системы на больших промежутках времени или искать тренды. Метрики. Логирование – это хорошо, но мало. Для прозрачной работы системы и разбора инцидентов нужны метрики. Также по метрикам можно легко посмотреть тренды по нагрузке, количеству пользователей системы, запросам и так далее.  Мы добавляем общие метрики: нагрузка системы, количество и размер запросов, количество успешных и неуспешных запросов, время ответа сервера и другие. Особенно полезно добавить такие метрики в общие библиотеки, тогда метрики «прорастут» во все сервисы, и командам не придется их отправлять самостоятельно.  В основном для метрик мы используем временное хранилище, но самые важные метрики стараемся сохранять в долговременном. Это помогает нам смотреть тренды за большой промежуток времени.  Конечно, мы также учим команды создавать свои метрики, рассказываем, куда их нужно отправлять и как визуализировать на графиках. Визуализация — лучший инструмент поиска причины инцидента. На основе метрик можно создавать алерты и другие нотификации.  Пример визуализации 4хх ответов сервиса с разбивкой по хендлерам:  Алерты. У SRE команды есть свои базовые алерты на доступность сервисов, нагрузку серверов и так далее, но они явно не покрывают все потребности бэкенд-команды. Поэтому мы создаем свои алерты для тех случаев, когда нам важно знать, что внутри приложения что-то пошло не так.  Пример такого алерта — значительно увеличилось время ответа важного хендлера. Это еще не приводит к отказе работы сервиса, но подсвечивает проблему с быстродействием. Мы делаем алерты не только на случай, когда все плохо, но и для того, чтобы заранее предотвратить такие ситуации.  Мы используем как общие для всех алерты (превышен рейт 500 по эндпоинту), так и узкоспециализированные (время выгрузки специфического отчета превысило допустимый лимит). Каждая команда получает свои специфические алерты в командный чат, а общие отправляются в канал, где их разбираем мы. Логирование, метрики и алерты помогают нам быстро реагировать, разбираться в причинах инцидентов и решать проблемы. Дальше нам нужно сделать так, чтобы инцидент не повторился. Для этого мы используем следующие инструменты: rate limiter, circuit breaker, caches.   Кэши. Мы активно применяем кэши при взаимодействии с базами данных, чтобы разгрузить их и быстрее получить данные. Кэши создаем как локальные (с помощью Caffeine) внутри каждого инстанса сервиса, так и распределенные (на основе Redis). При таком подходе могут возникнуть проблемы, связанные с актуализацией значений в локальных кэшах распределенной системы, но мы умеем их решать, с помощью pub/sub механизма для рассылки событий инвалидации между сервисами.  Rate limiter — контроль количества запросов, которые может сделать пользователь. Этот инструмент мы используем для уменьшения нагрузки на систему. Он помогает лучше распределять серверные мощности между пользователями и не забивать все пулы тяжелыми запросами или сломанными интеграциями.  Мы умеем гибко конфигурировать rate limiter —  это позволяет давать больше возможностей тем, кому это действительно необходимо. Мы используем два типа контроля: контроль количества запросов за промежуток времени и контроль количества процессорного времени, которое затрачено на запросы. Это помогает избежать и большого количества мелких запросов, и тех случаев, когда пользователь укладывается в лимит, но его запросы очень медленные или ресурсоемкие.  Circuit breaker (CB) — паттерн, который в случае возникновения проблем с доступностью сервиса перестает пропускать к нему запросы до тех пор, пока доступность не восстановится. Этот паттерн помогает нам быстрее восстановиться в том случае, если возникли проблемы с какой-либо частью нашей системы или внешней.  Инструмент особенно полезен при решении проблем с сетевой связностью между компонентами. Запросы к системе, по которой открыт CB, перестают отваливаться по таймауту, а сразу завершаются с ошибкой. Это не забивает пулы и помогает быстрее получить ошибку. Мы считаем, что деградация лучше, чем полная неработоспособность. В некоторых случаях при срабатывании CB мы полностью обрываем все открытые соединения с проблемной системой и пытаемся заново установить связь.  Такой базовый набор облегчает нашу работу, позволяет быстро и эффективно решать возникающие проблемы и помогает предотвращать повторение этих проблем в будущем. Но самое главное, что хочется подчеркнуть — за всеми этими инструментами и технологиями стоят люди. Именно благодаря команде backend reliability специалистов, которые умеют эффективно использовать эти инструменты и всегда готовы найти решение любой проблемы, мы можем обеспечить высокое качество продукта. Мы постоянно ищем новые подходы и технологии, которые позволяют нам сделать наш сервис более надежным и учат нас справляться с любой нагрузкой. Мы стараемся заранее понять, какие части системы нужно улучшить, чтобы удовлетворить потребности растущего бизнеса.  Буду рад ответить на вопросы и комментарии про работу нашей команды.