При проектировании нагруженных систем приходится сталкиваться с тем, что разные типы запросов к веб-серверам затрачивают разное количество ресурсов, выполняются за разное количество времени и имеют разные приоритеты выполнения. Некоторые запросы «стоят» мало и должны выполняться как можно быстрее. Некоторые «стоят» дорого, и главное, чтобы они не блокировали обработку быстрых запросов. Существующие схемы приоритезации показались нам громоздкими и неудобными – при росте количества типов запросов конфигурация системы усложнялась в разы. Поэтому, чтобы решить эту проблему, а также для того, чтобы сделать ответы на запросы еще более быстрыми, мы написали свой веб-сервер – Phantom. Я расскажу вам, как он устроен, покажу, какие задачи можно решать с его помощью, а в завершение покажу на практике, как работает приоритезация разных типов запросов, используя для этого инструмент нагрузочного тестирования, основанный на Phantom.
6. Проблемы?
— Если worker-ов больше чем процессоров —
возникает конкуренция за процессор.
— Worker-ы могут блокировать друг-друга.
— Если все worker-ы заблокированы, запросы
накапливаются в очереди и ждут, когда
освободится worker.
6
7. Добавим скорости
Accelerator:
- “легкий” HTTP-сервер
- обрабатывает быстрые
запросы
- обеспечивает Keep-Alive
- проксирует запросы к
Frontend-у
7
9. Все, что мы сделали — это
разделили запросы к системе
на два типа.
9
10. Профит!
— Запросы поделились на два типа —
статика и динамика.
— При правильной конфигурации статика
будет отдаваться, даже если нет
свободных worker-ов.
10
11. Что будет, если добавить в
нашу систему еще один тип
запросов?
11
13. Не так страшно
— Для привязки worker-процессов к
процессорам можно использовать
cpu_affinity или cgroups.
— При правильной конфигурации статика
будет отдаваться, даже если нет
свободных worker-ов.
13
20. Phantom
• Конечный автомат (FSM)
• EPOLL-based
• Coroutine и continuations
• Написан from scratch
• Сильно оптимизирован
20
21. Phantom
• Не совсем честный FSM
• Worker thread-ы можно групировать в
пулы
• Пулы можно привязывать к процессорам
• Обработку разных типов запросов можно
отдавать в разные пулы
• Pure C++! :)
21
30. Нить выполнения
- принять соединение
- изготовить continuation
- передать его протоколлеру
- распарсить запрос
- переложить continuation
в соответствующий scheduler
- передать управление соответствующему
хэндлеру
30
33. И ещё раньше чем мы
научили phantom отвечать на
запросы, мы научили его их
задавать.
33
34. Для этого пришлось написать
отдельный модуль,
использовав уже
существующий планировщик.
34
35. Нить выполнения
- изготовить необходимое количество
continuation-ов
- передать их протоколлеру
- вычитать запрос из лога
- отправить запрос если пришло время
- вычитать и распарсить ответ
- обновить статистику
35
36. Phantom
Инструмент для нагрузочного
тестирования
— Поддержка любых stateless-протоколов
— Равномерность создаваемой нагрузки
— Высокая производительность
— На его основе написан фреймворк для
нагрузочного тестирования - Lunapark
36
37. Пример запроса
306 100
GET /su/ HTTP/1.1
Host: ****.yandex.ru
Accept: */*
Connection: close
Referer: http://afisha.yandex.ru/spb/events/?category=cinema&page=2
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; ru-ru)
AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16
X-Real-IP: xxx.xxx.xx.xxx
37