3. Зачем?
Контролируемая деградация
• Лучше не показать часть информации на странице, чем 500ка
• Лучше показать пользователю самое важное за 100ms, чем всё за 10s
4. Зачем?
Разные требования к компонентам
• Не все сервисы нужно писать под под большую нагрузку
• Некоторые сервисы могут и “полежать” какое-то время
• Усложняем и оптимизируем только там, где это требуется
5. Зачем?
Разработка на разных языках
программирования
• Выбираем N языков программирования – упрощаем поиск разработчиков
• Под какие то задачи подходит один ЯП, под другие другой
• На разных ЯП разная скорость разработки
7. Как?
Виртуализация
• Чтобы приложения не мешали друг другу, используем виртуализацию (kvm)
• Легко деплоить – на одной машине только одно приложение
• Из-за виртуализации получили сетевые задержки между виртуальными
машиными, вылечили использованием SR-IOV
8. Реальность!
• Много разных конфигов
• Усложнение деплоя
• Усложнение мониторинга
• Усложнение разработки
• Усложнение поиска проблем: был лог приложения, стало много логов разных
сервисов
• Усложнение поддержки тестовых стендов и рабочих станций разработчиков
9. Про логи
request_id – уникальный идентификатор
запроса.
• Генерируется на фронтендах: nginx + ngx_http_requestid_module
• Пробрасывается на все сервисы http заголовком
• Все записи в логах содержат request_id
10. Про логи
started GET /page/index/
got 200 http://192.168.1.172:8009/hh-session?args in 6.49ms
got 200 http://192.168.1.172:8021/xml/article/?args in 4.81ms
finish group: 10 requests pending
got from memcache: KEYS, blocking time: 1.07 ms
applied XSL ambient/index.xsl in 24.78ms
applied postprocessor '<Fuchakubutsu>' in 12.94ms
Stages for /page/index/ : session:9.47ms page:81.23ms xsl:24.78ms postprocess:13.27ms
200 GET /page/index/ (192.168.1.188) 174.31ms
Уже можно понять, как обрабатывался запрос, но логи размазаны
по разным серверам.
11. Про логи
Сливаем логи через syslog на один сервер
• искать по request_id долго
• проблемы с большими сообщениями
12. Про логи
Пробуем logstash, graylog2
• не справляются с нашей нагрузкой (20k messages/second), по крайней мере
за вменяемое время не удалось победить
• сложно доделать под наши задачи
• у graylog2 есть отличный протокол: GELF
13. Про логи
GELF
• UDP
• JSON + GZIP
• Поддержка больших сообщений (chunks)
• Есть готовые библиотеки для java, python, php, perl, ruby итд
• Очень простой – ничего лишнего
14. Про логи
Написали сервер
• 2 дня разработки на python
• Держит нашу нагрузку
• Сообщения пробовали хранить в cassandra и mongodb: выбрали mongodb
• Хранилище фиксированного размера (перезапись по кругу)
• Шардинг по request_id
• Быстрый поиск по request_id, можно добавить индексируемых полей
• Интерфейс поиска от консольных скриптов до web
• Легко расширять
15. Про логи
Научились собирать и искать по логам, учимся
писать логи
• В логи надо писать всё, что может пригодиться
• Если идём куда-то по сети: пишем зачем, куда, что ответили (статус), сколько
ждали ответа
• Если делаем вычислительную задачу: пишем что делали, сколько заняло
времени, ошибки
• Если ошибка: пишем во время какого запроса произошло, что в итоге (отдали
500 итд).
16. Про логи
Идеальное приложение с точки зрения
эксплуатации
• По логу можно понять, чем сейчас занято приложение и чем оно было
занято в момент времени X
• Если приложение тормозит или “плюется” ошибками:
можно понять – это внешние проблемы или проблемы самого приложения
разработчик по логу может понять причину такого поведения
17. Про мониторинг
• Мониторить параметры серверов нужно, но это не главное
• Ключевые метрики – про сервис, а не железо
• CPU Usage = 100% проблема? Нет! Зачастую это просто вспомогательная
информация
20. Про мониторинг
• Мониторим каждый экземпляр сервиса отдельно
• Сервис в целом на основе логов балансировщика
• Отдельные страницы сайта на основе логов фронтендов (ключевые
метрики)
21. Про мониторинг
• Нужно определить, что значит “сайт работает”, ”сайт не работает”
• Реальные проблемы:
95 персентиль времени ответа > N ms
процент ошибок > M
количество запросов резко упало / выросло
• Алерты должны быть только по делу
• Отчеты о доступности должны быть на основе метрик сервиса
22. Про деплой
Что должна уметь система выкладки
• Выложить сервис N, а только после этого сервис М
• При выкладке сервиса N применить изменения в конфигах
• Сервис N выкладывать параллельно по 2 экземпляра, идти дальше если оба
ответят по /status 200м статусом
• Помнить предыдущие версии каждого сервиса
• Откатиться на предыдущую версию
• Знать конфигурацию всего кластера: где живую экземпляры сервиса N,
сколько их итд
23. Про деплой
Как сейчас
• Скрипты на shell
• Простой шаблонизатор конфигов
• Деплой через ssh + scp + apt-get
• Описание конфигурации кластера в текстовых файлах
• Все достаточно громоздко
24. Про деплой
Куда идём
• Puppet для конфигов в роли репозитория (отключен autosync)
• Скрипты на python + fabric (не пишем логику параллельного исполнения, не
пишем обвязку для ssh, более умная проверка статусов сервисов)
• Выкладка только установкой deb пакетов
• Описание конфигурации кластера берем из мониторинга (базы) – она там
уже есть в самом актуальном виде
25. Итоги
• Разделение монолитного приложения на сервисы может принести пользу
• Отдельные подсистемы можно сохранить простыми
• Система в целом усложняется, особенно в эксплуатации
• Придется совершенствовать инфраструктурные инструменты для
сохранения контроля над системой:
- деплой
- логи
- мониторинг
26. Некоторые наши наработки на
http://github.com/hhru
• Frontik
• Logserver – очень грязный прототип (as is), лучше так чем никак =)
• nginx_requestid – модуль nginx для генерации request_id
27. СПАСИБО!
Николай Сивко
Директор по эксплуатации, HeadHunter
sivko@hh.ru