Привет! Мы в МТС Digital умеем и любим создавать высоконагруженные IT-решения. Для вывода таких продуктов в промышленную эксплуатацию необходимо научиться решать задачи постоянного самоанализа работоспособности, мониторинга, проверки соответствия заявленным SLA.

Меня зовут Глеб Тильтиков, я технический руководитель омниканальной платформы MTC OmniChannel, и о внедрении самодиагностики в IT-продукте большой цифровой экосистемы и пойдёт речь в этой статье.

При создании любой высоконагруженной системы (обрабатывает десятки или сотни тысяч запросов в секунду), которой, в частности, является наша омниканальная платформа МТС OmniChannel, важно на этапе проектирования архитектуры заложить в неё возможность масштабирования. Нам было необходимо выстроить средства наблюдения так, чтобы мы сами были полностью уверены в работоспособности продукта, его безотказности и соответствии заявленному уровню оказания сервиса, то есть SLA.

Например, наша система обслуживает более 20 тыс. запросов в секунду и должна быть доступна 99,99% времени. Так как пользователями нашего сервиса являются крупнейшие бизнесы, то основными нефункциональными требованиями выступают скорость и надёжность.

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

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

Как работает самодиагностика?

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

Закладывать возможность гибкой самомодификации стоит на этапе разработки архитектуры, которая требует продуманной стратегии, и вот как мы её выстроили:

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

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

  3. Собираем статистику как по общим данным, так и по конкретным потокам для последующей автоматизации принятия решений.

  4. Настраиваем предиктивную аналитику для нестандартного поведения нашей системы и партнёрских платформ, для которых потребителями являемся уже мы.

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

Обычно выделяют четыре уровня критичности:

  • mission critical;

  • business critical;

  • business operational;

  • office productivity.

На картинке — HLD-архитектура нашего realtime-контура. Красным отмечены mission-critical-компоненты, жёлтым — business critical, фиолетовым — business operational.

Класс критичности зависит от тяжести последствий и скорости их наступления. Единственный важный критерий, который используется в выявлении класса, — это убытки, которые понесёт компания вследствие остановки системы.

Итак, мы ввели категоризацию уведомлений по уровню полноты и информативности:

  • Alert;

  • Ticket;

  • Logging.

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

Далее займёмся мониторингом, он может быть пассивный и активный.

Пассивный будет анализировать данные, которые приходят от клиентов, а активный — создавать данные сам. Для этого нам нужно создать генераторы запросов, предусмотреть принимающий их эмулятор, чтобы он был максимально похож на живые данные. В дополнительном независимом дата-центре мы включаем генератор трафика на один из наших протоколов, например самый популярный — SMPP, и привязываем к нему внешнюю систему уведомлений. В самой первой версии нашего генератора была отправка виртуального SMS через каждые 15 секунд. Затем появилось зашумление, «рваные» интервалы, росло количество анализируемых каналов и протоколов.

Все компоненты real-time-контура дублируются, а над каждым принимающим/входящим трафик-портом установлен микроклиент-генератор, который создаёт тестовый трафик. Такой трафик проходит через платформу по обычному маршруту, достигает эмулятора, возвращает соответствующий тесту статус. Это происходит постоянно, с определённой периодичностью.

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

Как мы формируем систему самодиагностики:

  1. Определение критериев ожидаемого поведения, соответствия SLA. Нам нужно понять, что является нормой по каждому компоненту, а что аномалией.

  2. Процесс должен идти непрерывно по схеме «Проверка — Алерт — Решение — Возврат».

  3. В данном случае наш «супералерт» выглядит как рост неожиданного поведения. На основе такого оповещения мы принимаем решение.

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

Bypass — это обход, механизм, который задействует самый короткий маршрут для трафика внутри платформы, отключает все некритические функции и проверки. Его задача — только принять трафик и направить его в нужный канал доставки (фактически в этом и заключается наша главная миссия). Этот компонент также создаёт определённый лог, в него сохраняются данные в формате, необходимом для устранения последствий сбоя, чтобы мы могли позже восстановить все отсутствующие данные потребителей и статистику, провести тарификацию и т. п.

Что происходит, когда у нас срабатывает самодиагностика?

  1. Определение источника проблемы, аварийного порта.

  2. Откат версии кода в предыдущее состояние (во время пострелизного мониторинга).

  3. Поднятие инстансов.

  4. Синхронизация данных.

  5. Возврат порта в работу. Трафик на него вернётся автоматически, с учётом веса этого порта в настроечном конфиге.

  6. Пересчёт данных в статистике и биллинге.

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

Почему важно и нужно тестировать систему в production-среде?

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

Чтобы этого избежать, мы расширили наши привычные тесты, которые выполняются в CI/CD-конвейере, дополнив их тестами «непрерывной самодиагностики». Мы назвали их CC (continuous check). Это простые линейные алгоритмы, определяющие суть проверки. Для этого мы разработали специальную подсистему — тестовый фреймворк. Он создан на основе Golang + Testify, состоит из ядра и SDK, который могут использовать тестировщики. Мы последовали идеологии Twilio, которая поставляет единую готовую библиотеку, наделённую сразу же всеми омниканальными возможностями «из коробки».

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

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

Важно понимать и смириться с тем, что построить систему самодиагностики «сразу правильно» не получится. В случае, если вы разрабатываете enterprise-решения, нужно осознавать, что и самодиагностика будет эволюционировать вместе с вашим IT-продуктом.

Тем, кто хочет стать экспертом в управлении инцидентами, понимании принципов и выстраивания работы службы обеспечения надёжности, рекомендую прочитать Google SRE book, вот ссылка: https://sre.google/books/.

А начать решать задачу обеспечения надёжности стоит с простого, но гибкого механизма Check Engine.

Комментарии (0)