Новые релизы сайта booking.com выкладываются в продакшн постоянно и практически без тестирования. Есть минимальный mock testing, который выполняется непосредственно девелопером, но официальной процедуры тестирования нет. Происходит около 70 roll out в день, таким образом, какая-то из частей сайта обновляется примерно каждые 5 минут. Процесс развертывания фиксируется в общем чате jabber.
Идет процесс постоянного экспериментирования, выстраивания гипотез и их проверки. То, что не получилось, отбрасывается, и пробуется новое. Отрабатывается более чем тысяча активных экспериментов постоянно. Как разрабатывать код без тестирования? Такая модель разработки строится на трех столпах.
Модель разработки:
- Ownership – именно разработчик несет ответственность за работу релиза. В случае проблемы со своим кодом, он должен исправить проблему. Если девелопер развертывает чужой код, он должен обеспечить исправление ошибок. То есть найти человека, который владеет подсистемой, и убедиться, что проблема решена.
- Fast reverts – быстрые откаты. В случае возникновения проблем релиз откатывается за несколько минут.
- Visibility – это суммарно мониторинг и аллертинг. Так как нет тестирования, налагаются дополнительные требования на систему мониторинга. Она должна вовремя оповещать и предоставлять исчерпывающую информацию.
Подробнее про Visibility.
Ключевые метрики.
У компании огромное количество разнообразных метрик. Кроме обычных технических и бизнес метрик есть специфичные.
Самая основная метрика – «количество бронирований». От нее у booking.com зависит объем заработанных денег в секунду. Она релевантная для каждого девелопера.
Если случается проблема, метрика «количество бронирований» определяет ход действий. Если она падает, обязательно начинает раскручиваться механизм эскалации. Если по-прежнему проблема есть, включается больше ресурсов. Если «количество бронирований» не затронуто, то проблема не так критична, и можно исправить её постепенно.
Другая важная и необычная метрика – «бюджет на ошибки». Это, грубо говоря, определенная денежная дельта. Та цена, которую booking.com платит за быструю разработку, быстрые эксперименты и быстрое движение вперед. Она необходима, так как отсутствие тестирования увеличивает вероятность сбоев. Если компания потеряла меньше этой суммы, то всё в норме. Если бюджет превышен, включается механизм эскалации. Так же не является нормой, когда «бюджет на ошибки» очень низкий. Это косвенно говорит о том, что разработка проходит медленно, и есть возможность разрабатывать код быстрее, допускать ошибки. Есть запас, дельта, которая позволяет это делать.
Эскалация проблем.
Этапы:
- Общий чат в jabber. Тут происходят все коммуникации по roll out кода и первичное обсуждение проблем. После общения, если решается, что проблема есть и…
- Стартует конференц-связь. Есть единый номер. В обсуждении участвуют релевантные девелоперы. Ответственные люди присоединяются в конференц-звонок. Далее…
- Определяется лидер, который отвечает за:
- Координацию – решает кто чем занимается.
- Оповещение компании – сотрудники, отделы должны иметь возможность получить информацию о происходящем.
- Коммуникацию с вышестоящим менеджментом – руководство должно быть в курсе.
- Привлечение ресурсов – подключает других девелоперов, администрацию по необходимости.
- Проблема полностью решается, но после завершения конференц-звонка инцидент не считается завершенным.
- Далее следует RFO – «reason for outage». Кто-то должен сесть, не обязательно виновник, и определить:
- В чем причина?
- Какие факторы, совокупность факторов, способствовала развитию проблемы?
- Каким образом, возможно, избежать такого класса ошибок?
- В принципе возможно ли автоматизировать такой класс ошибок?
- Насколько были эффективны аллерты?
- В очень критичных ситуациях, происходит этап «post mortem». Группа инженеров разбирает инцидент подробно и принимает меры, чтобы подобное не повторилось.
Инструменты оповещения
У компании есть большой набор внутренних инструментов. Было несколько причин разрабатывать свои. Во-первых, когда возникла необходимость, ничего на рынке не было. Во-вторых, иногда есть смысл писать то, что хорошо работает именно для компании.
В основе работы оповещения – «events system».
Как устроена «events system»?
Есть набор серверов. Каждый сервер обслуживает запрос и формирует сообщение. Оно включает в себя огромное количество различной информации. Все сообщения уходят в центральную систему – events pipeline. На данный момент реализовано на Apace Kafka.
И есть consumer – инструмент, который извлекает нужную информацию и использует.
Ddos_detector – один из consumer. Его задача читать и анализировать events real-time. Внутренний инструмент компании, развивается давно и отвечает за наиболее критичные показатели системы. Он обеспечивает real-time анализ трендов по метрикам. И, если какое-либо значение значительно ниже или выше, чем было до этого или чем предсказывается, он отправляет аллерт, который идет в общий чат jabber.
Nagios
Назначение – мониторинг технических характеристик. Например: место на диске закончилось, %CPU высокий и т. п.
Bosun – open source application specific инструмент. Он периодически опрашивает данные, анализирует и высылает информацию. Любой разработчик может добавить свой модуль и получать данные.
Flog.
Разработанный booking.com инструмент. Показывает актуальное текущее состояние системы. Девелопер контролирует процесс через Flog. Когда разработчик начал roll out и код отправлен в продакшн, он смотрит за состоянием системы по графикам (желтый квадрат). Можно включить режим, когда на графиках в момент начала roll out появляется вертикальная линия.
Есть в ней функции фильтрации.
Есть колонка с количеством хостов, которые генерируют проблему (желтый квадрат).
Колонка с количеством IP, с которых идет ошибка (желтый квадрат).
Агрегированные ошибки и предупреждения (зеленый квадрат). Реализовано это за счет регулярных (regex) выражений, которые группируют ошибки с одинаковым паттерном.
Колонка owner (фиолетовый квадрат). Здесь информация о том, кто конкретно занимается решением проблемы. Если пока никто не решает, вместо информации кнопка «own it».
В самом верху инструкции по разворачиванию механизма эскалации (красный квадрат).
Graphite/grafana
Обрабатывает миллионы метрик разной природы.
Источники данных для graphite:
Diamond – коллектор написанный на питоне. Он собирает статистику системных метрик.
Graphite processor – так же разработанный booking.com инструмент, основанный на events. Является ориентированным на пользователя фреймворком. Позволяет разработчику написать свой модуль, развернуть его и использовать для контроля своего релиза. Использует метрики, специфичные для модуля, обрабатывает их, собирает статистику и отправляет в Graphite. Строит завершенные графики.
Ddos_detector – кроме функций оповещения, так же пишет графики. Использует набор стандартных метрик, которые точно посчитаны верно. Это бизнес метрики, такие как «распределение по странам» «по провайдерам». И технические метрики (pv, error/warning, wallclock percentiles, др.) Задача оставаться real-time.
В чем разница между Graphite processor и Ddos_detector? Они оба берут данные из потока events, обрабатывают, строят графики и отправляют в Graphite. Во-первых, код Ddos_detector является всегда валидным. В случае серьезных проблем нужна достоверная информация, а модуль разработчика, написанный для Graphite processor, может содержать ошибки.
Во-вторых, есть отличия в созданных графиках.
К примеру, есть график таймингов пользователя при нормальной работе:
В случае если есть проблема и система перегружена, график Graphite processor будет отставать от настоящего времени:
Допустим, 19-ую секунд Graphite processor обрабатывал не 1 секунду, а 10 секунд. Далее он будет обрабатывать 30-ую секунду, а писать ее на месте 20-ой. Хотя по факту это будет 30-ая, на графике она будет отрисована на месте 20-ой. Он строит завершенные графики.
Ddos_detector же пишет информацию вовремя, но секунды задержки пропускает:
То есть он будет обрабатывать 30-ую секунду и писать ее на месте 30-ой. Он остается real-time и построен так, чтобы «умирать» последним. Критично важно, чтобы мониторинг выдерживал атаку и проблемы. Система events так же должна «умирать» последней. Это ключевые условия.
Kibana.
Используется классический workflow, когда на локальной машине установлен rsyslog демон. Он направляет все сообщения в центральную распределенную очередь (Apache Kafka). Оттуда мессенджи оправляются в Elasticserch. Через него Kibana может получать нужную информацию и строить графики.
Внедрение Graphite в booking.com
Стандартный graphite open source стек не в состоянии справится с нагрузками компании. Поэтому он переписан полностью.
Схема того, что было:
Front-end сервера занимаются рендером. Back-end — занимаются хранением данных.
Какие были проблемы с Graphite:
- Carbon-relay – SPOF. Он один на дата-центр. Его тяжело конфигурировать одновременно на несколько дата-центров.
- У carbon-relay статическая конфигурация. Поэтому данные различаются, если есть ошибки при записи. Если один из дата-центров выпал или одна машина выпала, то одна из операций записи произойдет с ошибкой и данные записаны не будут. Когда машина восстанавливается, то получается, что какие-то данные отсутствуют. И когда идет запрос на запись, получается различный результат или данных может не быть.
- Время ответа растет линейно с ростом количества серверов. Graphite web опрашивает машины последовательно. Чем больше graphite кластер, тем дольше идет запрос.
- Graphite стек написан на Python Работает не очень быстро и его сложно масштабировать.
Как изменили Graphite:
- Carbon-relay, написан на «Си». Производительность увеличена до одного миллиона метрик в секунду на двух ядрах. В него включен функционал load balancer: он сам распределяет нагрузку по storage nods. В него включена функция агрегирования: он буферизирует данные, если upstream не доступен. Может быть выстроен в древовидной форме.
- Carbon-zipper. Написан на Go.
Он объединяет данные так, как показано на схеме:
То есть выпады, которые получаются в результате проблем, исключаются, и данные возвращаются всегда одинаковые.
- Graphite WEB – это модуль, который рендерит запрос и строит .png. Переписан на GO и в результате время отклика уменьшилось в 19 раз. Не только стало работать все быстрее, но и появилась возможность делать сложные запросы.
- В Carbonapi реализовали новые математически сложные операции. Между graphite web и carbonapi существует несовместимость, но она подробно документирована.
Два трюка с Graphite.
- Первый. По умолчанию при работе с bucket функция агрегирования в Graphite – average. Но этот способ не всегда подходит. Поэтому важно задавать правильную функцию агрегирования. Разные функции можно задать, используя naming convention. Тогда по метрикам с определенным названием применяются нужные методы агрегации.
- Второй. Graphite, когда рендерит, использует определенное количество пикселей по ширине. И если данных больше, то на каждый пиксель приходиться больше единицы данных, например, может быть сотня. По умолчанию он применяет функцию average. Но если применять функцию consolidateBy, то Graphite использует максимальное значение и график будет построен правильно.
Open-source ссылки
carbonzipper – github.com/dgryski/carbonzipper
go-carbon – github.com/lomik/go-carbon
carbonsearch – github.com/kanatohodets/carbonsearch
carbonapi – github.com/dgryski/carbonapi
carbon-c-relay – github.com/grobian/carbon-c-relay
carbonmem – github.com/dgryski/carbonmem
Carbonmem – in memory storage для метрик. Для чего Carbonmem? Когда пишешь одну метрику, память алоцируется под количество метрик на неделю, к примеру. В отличие от стандартного Graphite, Carbonmem умеет хранить короткий промежуток времени в памяти.
About The Author
Виктор Карабедянц
ИТ директор (CIO), руководитель нескольких DevOps команд. Профессиональный руководитель проектов по внедрению, поддержке ИТ систем и обслуживанию пользователей.