SlideShare a Scribd company logo
Использование асинхронного I/O для
снижения потребления ресурсов в
движке aviasales
Каплуновский Борис
aviasales.ru
facebook.com/boris.kaplounovsky
@bskaplou
Agenda
● Скриптовые языки и ресурсы
● Асинхронная модель выполнения
● Оптимизации и отзывчивость
● Странности Tornado
● Странности Python
● Tornado/Python в production
● И ещё пару советов по повышению
производительности...
Что делает движок aviasales
Модель памяти нативной
программы
process one
stack
data
process two
code
libdl
libc
data
stack
● Одна и та-же память с
исполняемым кодом
используется всеми
процессами
● Разделяемые
библиотеки грузятся в
память один раз
● Не разделяются
другими процессами
только сегменты
данных и стек
Модель памяти скрипта
runtime code
libdl
libc
stackstack
data data
script libs script libs
● Нативные код и
библиотеки
разделяются
● AST и байткод
скриптовых библиотек
хранятся в сегменте
данных и поэтому НЕ
разделяются
● Скриптовый код не так
компактен как
нативный и обычно
занимает в разы
больше памяти
code code
Сферический CGI Сервер в
вакууме
stack
data
native code
libc
libdl
datadatadatadata data
stack stackstack stack stack stack
Скриптовый CGI Сервер
stackstack
data data
script libs script libs
code code
stackstack
data data
script libs script libs
code code
stackstack
data data
script libs script libs
code code
native code
libc
libdl
Оптимизации над CGI
● fastcgi - Не порождаем отдельный процесс для каждого
запроса – экономим процессорного времени на
загрузку скриптов j2ee/rails/etc
● process pool - запуск и инициализация процесса до
прихода запроса – снижение времени отклика
● master -Запуск родительского процесса загружающего
код и делающего инициализацию. Родительский
процесс порождает обработчиков клонируя себя.
Процесс обрабатывающий запрос уже имеет в памяти
всё необходимое. unicorn/dalvik/etc
Copy on write
● После вызова fork() состояние
памяти и родителя и потомка
одинаковые
● Делать полную копию
адресного пространства при
fork() расточительно
● В момент вызова fork()
страницы данных родителя и
потомка метятся как read-only
parent childcode
libdl
libc
data
stack
fork()
Copy on write
● Как только один из процесс
записывает данные –
операционная система делает
личную копию страницы в
пространстве процесса
● Страницы памяти в которые не
пишут могут разделяться вечно
parent child
data
stack stack
data
clone pages
master process & copy on write
● После старта мастер процесс
грузит библиотеки и
подготавливает всё для
исполнения скрипта
● По мере необходимости мастер
порождает рабочие процессы
клонируя себя
● Так как в мастере уже были
загружены все библиотеки
дочерний процесс готов к работе
мгновенно
● COW позволяет не создавать
собственную копию кода в памяти
master child
stackstack
data data
script libs
code
native code
libc
libdl
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения потребления ресурсов в движке Aviasales.ru
Copy on write
НЕ РАБОТАЕТ!
COW не работает потому что
● GC скриптовой среды
меняют данные
неиспользуемых обьектов в
ходе своей работы
● Скриптовые языки со
счётчиками ссылок
модифицируют счётчики
ссылок при создании новой
ссылки на обьект, даже
если сам обьект неизменен
master child
stackstack
data data
script
libs
code
native code
libc
libdl
code
script
libs
COW не
просто заставить работать
● В ruby 2.0 обещали сделать
cow friendly gc. Не
получилось!
● COW работает у google в
dalvik, но для этого им
пришлось заменить jvm на
dalvik
master child
stackstack
data data
script
libs
code
native code
libc
libdl
code
script
libs
Типичное web приложение
Значительную часть времени веб приложения
ждут ответов внешних сервисов таких как
– SQL сервер
– Внешний API
– Файловый ввод вывод
Всё это время ничего не происходит!
Но память занята...
запрос ответ
logic SQL logicAPI
Rails приложение aviasales
● Ожидание ответа внешних API до 30 секунд
● Работа с SQL ~1 секунда
● Потребляемая память ~300mb (одним процессом)
● Разделяемая память ~4mb (код интерпретатора)
● ~300 одновременных поисков
87GB RAM/6 серверов
И вся эта память простаивала!
запрос ответ
logic SQL logicAPI
Синхронная модель VS
Асинхронная модель
cgi worker
stack
data
code
script
libs
cgi worker
stack
data
code
script
libs
async worker
stack
script
libs
code
native code
libc
thread
data
thread
data
thread
data
cgi worker
stack
data
code
script
libs
native code
libc
Асинхронная модель
Минусы
● Кооперативная многозадачность
● Если падает процесс падают все потоки
● Не для всего есть библиотеки
● Отсутствие изоляции
● Примитивный планировщик
● Нет готовых решений
Асинхронная модель
Плюсы
● Эффективное использование памяти
● Эффективное использование памяти
● Эффективное использование памяти
● Эффективное использование памяти
● Эффективное использование памяти
Почему Python
– Большое и доброе community
– Обилие библиотек
– Tornado живёт в python
– Реклама google
– Хотелось попробовать
Почему Tornado
– Низкий порог вхождения
– Асинхронный
– @gen.coroutine – отличная альтернатива
колбекам
– Казался зрелым
Приложение на python/tornado
● Один процесс:
– занимает 267mb памяти
– из них 162mb разделяемой
– обрабатывает до 10
одновременных запросов
– больше не ждёт SQL сервер, все
данные в адресном пространстве
процесса
– ~ 500 одновременных исходящих
соединений
– 2 сервера/8GB памяти
async worker
stack
script
libs
code
native code
libc
data data data
При работе с tornado помни!
● Как только вы начинаете использовать синхронный IO
всё останавливается
● Переключение контекста происходит ТОЛЬКО на I/O и
yield внутри @gen.coroutine
● Неделимый кусок кода не должен исполняться больше
XXXms (мы выбрали 100ms)
При работе с tornado помни!
● Декоратор @gen.coroutine не бесплатен
● Tornado/Python приложение может умирать
● У Tornado/Python приложения может течь память
● Только профилировщик точно покажет кто ест CPU
● Python используется как клей для нативных библиотек,
сложные алгоритмы на python реализовывать не надо
Странности Tornado
● Из коробки нет способа остановить приложение без
обрыва соединений
● Есть рецепты костылей на StackOverflow
● Но этого мало – пришлось изобретать ещё костылей
Резольвер
www.aviasales.ru → 194.87.255.204
● “Родные” резольверы операционных систем
синхронны
● Для асинхронный модели исполнения нужен
асинхронный резольвер
Странности Tornado – Резольвер
● tornado.netutil.BlockingResolver
– Используется по умолчанию
– Использует синхронный getaddrinfo
– Не кеширует результаты
– Обращение к DNS при каждом HTTP
запросе
– Пока DNS сервер не ответил всё стоит
Странности Tornado – Резольвер
● tornado.netutil.ThreadedResolver
– Вызывает getaddrinfo в отдельном потоке
python
– Overhead на потоки: память, cpu, GIL
– Работает но выглядит как костыль
Странности Tornado – Резольвер
● Мы написали простой
асинхронный резольвер для
Tornado IOLoop
– Только TCP
– Только записи A и CNAME
– Кеширование ответов DNS по
TTL
– Большинство
преобразований делается без
системных вызовов
Странности Tornado – HTTPClient
● HTTPClient создаёт не больше 10 исходящих
соединений по умолчанию
● HTTPClient умеет стримить ответ сервера только
если ответ chunked
Странности Tornado
● Документация зачастую избегает описывать узкие
места
● Будьте готовы читать исходный код tornado чтобы
понять поведение системы
Странности Python
● Сторонние библиотеки с нативным кодом текут и валят
приложение через одну
● Найти утечку памяти в нативном коде крайне сложно
● Встроенная библиотеку xml.etree может приводить к
SEGFAULT, мы используем lxml
● Сложные регулярные выражения могут остановить
приложение busy-wait
tornado/python в production
MONIT
– Убивает рабочие процессы если они
выедают CPU
– Убивает рабочие процессы если они
превысили лимит по памяти
– Стартует рабочие процессы если те
умерли сами или были убиты
– Простой и удобный web интерфейс
tornado/python в production
HAPROXY
– Раскидывает приходящие запросы по
доступным рабочим процессам
– Балансирует нагрузку отправляя
запросы к процессам с наименьшим
количеством активных соединений
– Адски быстрый и простой
– Простой и удобный веб интерфейс
tornado/python в production
BENCHMARKS
– Тотальное логирование времени выполения участков
кода
– Визуализация бенчмарков на видном месте
– Немедленная реакция на аномалии в скорости
ответов сервера
Что делать с ожиданием ответов
SQL сервера
Удалённый сервер DB
request
response
worker remote db
parse request
load value
build response
recv(syscall)
send(syscall)
Файловое key-value хранилище
● Содержимое файла должно быть смаплено в
адресное пространство процесса mmap
● Рабочий обьём должен умещаться в оперативной
памяти
● База должна позволять нескольким процессам
одновременно читать данные без блокировок
● Мы используем kyoto cabinet и он прекрасен
Быстрее чем redis и memcached
worker
load value
Плюсы
● Не нужен внешний
сервер
● Непревзойдённая
скорость
● Не нужно переключать
контекст и делать
syscall
● Высокая
отказоустойчивость
Быстрее чем redis и memcached
worker
load value
Минусы
● Медленный update
данных
● Избыточность при
работе в кластере
● Работает только для
небольшого кол-ва
данных
Q&A
facebook.com/boris.kaplounovsky
@bskaplou
Используйте потоковую обработку
для разбора XML
● Опция streaming_callback у AsyncHTTPClient
fetch позволяет получать данные по мере
поступления
● Метод lxml.etree.XMLParser.feed позволяет
парсить xml по кускам
● Если и это не помогает, делаем
IOLoop.instance().add_timeout(time()) чтобы
разбить поток исполнения
tornado/python в production
Приоритеты
● У разных запросов разные требования к скорости ответ
● Рабочие процессы привязываются к одной или
нескольким группа приоритета
● Haproxy отправляет запросы в соответствующую группу
рабочих процессов

More Related Content

PDF
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
PPTX
Alexandr Serbul "The Rust language for a high-load network service - a quick ...
PDF
My talk on Graphite stack on 58it.ru
KEY
Что и почему писать на Erlang
PDF
Erlang мгновенное просветление
PDF
Лев Валкин — Кое-что про Erlang
PDF
Алексей Туля - А нужен ли вам erlang?
PPTX
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
"Мы два месяца долбались, а потом построили индекс" (c) Аксенов
Alexandr Serbul "The Rust language for a high-load network service - a quick ...
My talk on Graphite stack on 58it.ru
Что и почему писать на Erlang
Erlang мгновенное просветление
Лев Валкин — Кое-что про Erlang
Алексей Туля - А нужен ли вам erlang?
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...

What's hot (19)

PDF
Константин Осипов
PPTX
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
PDF
Олег Бартунов и Иван Панченко
KEY
Erlang&rails
PDF
Алексей Федоров
PPTX
Why we did not choose Hadoop
PDF
Erlang railsclub - 1
PDF
My talk on LeoFS, Highload++ 2014
PDF
Максим Лапшин — введение в Erlang
PDF
PDF
Опыт использования Erlang в разработке многопользовательской игры
PDF
JPHP - О проекте на простом языке
PDF
Erlang, который мы потеряли
PDF
Эффективная отладка репликации MySQL / Света Смирнова (Percona)
PDF
Там, где Rails не справляются
KEY
Отличие Erlang от объектных языков
PPTX
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
PDF
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
PDF
Мой modern Perl (весенняя встреча Piter United)
Константин Осипов
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
Олег Бартунов и Иван Панченко
Erlang&rails
Алексей Федоров
Why we did not choose Hadoop
Erlang railsclub - 1
My talk on LeoFS, Highload++ 2014
Максим Лапшин — введение в Erlang
Опыт использования Erlang в разработке многопользовательской игры
JPHP - О проекте на простом языке
Erlang, который мы потеряли
Эффективная отладка репликации MySQL / Света Смирнова (Percona)
Там, где Rails не справляются
Отличие Erlang от объектных языков
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Мой modern Perl (весенняя встреча Piter United)
Ad

Viewers also liked (8)

PDF
TFF2015, Gila Gfader, Booking.com, "Die Reise beginnt in Netz"
PDF
CodeFest 2014. Vedran Mikulic — Booking Fast Development
PDF
ConnectIn Amsterdam 2014 - Beter beslissen met data - Booking.com & Netwerven
PDF
Internationalisation: 2200+ different ways to view a website
PDF
The anatomy of an A/B Test - JSConf Colombia Workshop
PDF
Front-end Culture @ Booking.com
PDF
Tag-it 2016 slides: UX + A/B Testing at Booking.com: Design focused on conver...
PDF
Introduction of Booking.com
TFF2015, Gila Gfader, Booking.com, "Die Reise beginnt in Netz"
CodeFest 2014. Vedran Mikulic — Booking Fast Development
ConnectIn Amsterdam 2014 - Beter beslissen met data - Booking.com & Netwerven
Internationalisation: 2200+ different ways to view a website
The anatomy of an A/B Test - JSConf Colombia Workshop
Front-end Culture @ Booking.com
Tag-it 2016 slides: UX + A/B Testing at Booking.com: Design focused on conver...
Introduction of Booking.com
Ad

Similar to CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения потребления ресурсов в движке Aviasales.ru (20)

PDF
Разработка API для большого, нагруженного сервиса
PDF
Разработка API для большого, нагруженного сервиса
PDF
Павел Юрийчук - Разработка приложений под мобильные браузеры
PDF
Путь к Go на конкретном примере
PDF
Multithreading in JS. Myth or reality?
PPTX
SECON'2016. Чубарь Алексей, Мобильные грабли Unity
PDF
AVITO. Решардинг Redis без даунтайма. DevConf 2012
PPTX
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
PDF
Как считать и анализировать сотни гигабит трафика в секунду, Станислав Николо...
PDF
"How to build powerful CI / CD based on GitLab and Docker", Aleksandr Matkovs...
PDF
Другая виртуализация
PDF
Сетевой инженер 2.0. Что нужно знать о программируемости в корпоративной сети?
PPT
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
PDF
20111002 information retrieval raskovalov_lecture3
PPTX
Breaking logs
PDF
Async Python
PDF
CodeFest 2013. Лузин А. — Бэкенд-винегрет: как подружить разные ЯП на ваших с...
PPTX
О создании компилятора с высокоуровневого языка на компьютер с программируемо...
PDF
My talk on HBase ops engineering at TBD Jun 2016
PPTX
2014.12.23 Александр Андреев, Parallels
Разработка API для большого, нагруженного сервиса
Разработка API для большого, нагруженного сервиса
Павел Юрийчук - Разработка приложений под мобильные браузеры
Путь к Go на конкретном примере
Multithreading in JS. Myth or reality?
SECON'2016. Чубарь Алексей, Мобильные грабли Unity
AVITO. Решардинг Redis без даунтайма. DevConf 2012
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
Как считать и анализировать сотни гигабит трафика в секунду, Станислав Николо...
"How to build powerful CI / CD based on GitLab and Docker", Aleksandr Matkovs...
Другая виртуализация
Сетевой инженер 2.0. Что нужно знать о программируемости в корпоративной сети?
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
20111002 information retrieval raskovalov_lecture3
Breaking logs
Async Python
CodeFest 2013. Лузин А. — Бэкенд-винегрет: как подружить разные ЯП на ваших с...
О создании компилятора с высокоуровневого языка на компьютер с программируемо...
My talk on HBase ops engineering at TBD Jun 2016
2014.12.23 Александр Андреев, Parallels

More from CodeFest (20)

PDF
Alexander Graebe
PDF
Никита Прокопов
PPTX
Денис Баталов
PDF
Елена Гальцина
PDF
Александр Калашников
PDF
Ирина Иванова
PDF
Marko Berković
PDF
Денис Кортунов
PDF
Александр Зимин
PDF
Сергей Крапивенский
PDF
Сергей Игнатов
PDF
Николай Крапивный
PDF
Alexander Graebe
PDF
Вадим Смирнов
PDF
Константин Осипов
PDF
Raffaele Rialdi
PDF
Максим Пугачев
PDF
Rene Groeschke
PDF
Иван Бондаренко
PDF
Mete Atamel
Alexander Graebe
Никита Прокопов
Денис Баталов
Елена Гальцина
Александр Калашников
Ирина Иванова
Marko Berković
Денис Кортунов
Александр Зимин
Сергей Крапивенский
Сергей Игнатов
Николай Крапивный
Alexander Graebe
Вадим Смирнов
Константин Осипов
Raffaele Rialdi
Максим Пугачев
Rene Groeschke
Иван Бондаренко
Mete Atamel

CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения потребления ресурсов в движке Aviasales.ru

  • 1. Использование асинхронного I/O для снижения потребления ресурсов в движке aviasales Каплуновский Борис aviasales.ru facebook.com/boris.kaplounovsky @bskaplou
  • 2. Agenda ● Скриптовые языки и ресурсы ● Асинхронная модель выполнения ● Оптимизации и отзывчивость ● Странности Tornado ● Странности Python ● Tornado/Python в production ● И ещё пару советов по повышению производительности...
  • 4. Модель памяти нативной программы process one stack data process two code libdl libc data stack ● Одна и та-же память с исполняемым кодом используется всеми процессами ● Разделяемые библиотеки грузятся в память один раз ● Не разделяются другими процессами только сегменты данных и стек
  • 5. Модель памяти скрипта runtime code libdl libc stackstack data data script libs script libs ● Нативные код и библиотеки разделяются ● AST и байткод скриптовых библиотек хранятся в сегменте данных и поэтому НЕ разделяются ● Скриптовый код не так компактен как нативный и обычно занимает в разы больше памяти code code
  • 6. Сферический CGI Сервер в вакууме stack data native code libc libdl datadatadatadata data stack stackstack stack stack stack
  • 7. Скриптовый CGI Сервер stackstack data data script libs script libs code code stackstack data data script libs script libs code code stackstack data data script libs script libs code code native code libc libdl
  • 8. Оптимизации над CGI ● fastcgi - Не порождаем отдельный процесс для каждого запроса – экономим процессорного времени на загрузку скриптов j2ee/rails/etc ● process pool - запуск и инициализация процесса до прихода запроса – снижение времени отклика ● master -Запуск родительского процесса загружающего код и делающего инициализацию. Родительский процесс порождает обработчиков клонируя себя. Процесс обрабатывающий запрос уже имеет в памяти всё необходимое. unicorn/dalvik/etc
  • 9. Copy on write ● После вызова fork() состояние памяти и родителя и потомка одинаковые ● Делать полную копию адресного пространства при fork() расточительно ● В момент вызова fork() страницы данных родителя и потомка метятся как read-only parent childcode libdl libc data stack fork()
  • 10. Copy on write ● Как только один из процесс записывает данные – операционная система делает личную копию страницы в пространстве процесса ● Страницы памяти в которые не пишут могут разделяться вечно parent child data stack stack data clone pages
  • 11. master process & copy on write ● После старта мастер процесс грузит библиотеки и подготавливает всё для исполнения скрипта ● По мере необходимости мастер порождает рабочие процессы клонируя себя ● Так как в мастере уже были загружены все библиотеки дочерний процесс готов к работе мгновенно ● COW позволяет не создавать собственную копию кода в памяти master child stackstack data data script libs code native code libc libdl
  • 13. Copy on write НЕ РАБОТАЕТ!
  • 14. COW не работает потому что ● GC скриптовой среды меняют данные неиспользуемых обьектов в ходе своей работы ● Скриптовые языки со счётчиками ссылок модифицируют счётчики ссылок при создании новой ссылки на обьект, даже если сам обьект неизменен master child stackstack data data script libs code native code libc libdl code script libs
  • 15. COW не просто заставить работать ● В ruby 2.0 обещали сделать cow friendly gc. Не получилось! ● COW работает у google в dalvik, но для этого им пришлось заменить jvm на dalvik master child stackstack data data script libs code native code libc libdl code script libs
  • 16. Типичное web приложение Значительную часть времени веб приложения ждут ответов внешних сервисов таких как – SQL сервер – Внешний API – Файловый ввод вывод Всё это время ничего не происходит! Но память занята... запрос ответ logic SQL logicAPI
  • 17. Rails приложение aviasales ● Ожидание ответа внешних API до 30 секунд ● Работа с SQL ~1 секунда ● Потребляемая память ~300mb (одним процессом) ● Разделяемая память ~4mb (код интерпретатора) ● ~300 одновременных поисков 87GB RAM/6 серверов И вся эта память простаивала! запрос ответ logic SQL logicAPI
  • 18. Синхронная модель VS Асинхронная модель cgi worker stack data code script libs cgi worker stack data code script libs async worker stack script libs code native code libc thread data thread data thread data cgi worker stack data code script libs native code libc
  • 19. Асинхронная модель Минусы ● Кооперативная многозадачность ● Если падает процесс падают все потоки ● Не для всего есть библиотеки ● Отсутствие изоляции ● Примитивный планировщик ● Нет готовых решений
  • 20. Асинхронная модель Плюсы ● Эффективное использование памяти ● Эффективное использование памяти ● Эффективное использование памяти ● Эффективное использование памяти ● Эффективное использование памяти
  • 21. Почему Python – Большое и доброе community – Обилие библиотек – Tornado живёт в python – Реклама google – Хотелось попробовать
  • 22. Почему Tornado – Низкий порог вхождения – Асинхронный – @gen.coroutine – отличная альтернатива колбекам – Казался зрелым
  • 23. Приложение на python/tornado ● Один процесс: – занимает 267mb памяти – из них 162mb разделяемой – обрабатывает до 10 одновременных запросов – больше не ждёт SQL сервер, все данные в адресном пространстве процесса – ~ 500 одновременных исходящих соединений – 2 сервера/8GB памяти async worker stack script libs code native code libc data data data
  • 24. При работе с tornado помни! ● Как только вы начинаете использовать синхронный IO всё останавливается ● Переключение контекста происходит ТОЛЬКО на I/O и yield внутри @gen.coroutine ● Неделимый кусок кода не должен исполняться больше XXXms (мы выбрали 100ms)
  • 25. При работе с tornado помни! ● Декоратор @gen.coroutine не бесплатен ● Tornado/Python приложение может умирать ● У Tornado/Python приложения может течь память ● Только профилировщик точно покажет кто ест CPU ● Python используется как клей для нативных библиотек, сложные алгоритмы на python реализовывать не надо
  • 26. Странности Tornado ● Из коробки нет способа остановить приложение без обрыва соединений ● Есть рецепты костылей на StackOverflow ● Но этого мало – пришлось изобретать ещё костылей
  • 27. Резольвер www.aviasales.ru → 194.87.255.204 ● “Родные” резольверы операционных систем синхронны ● Для асинхронный модели исполнения нужен асинхронный резольвер
  • 28. Странности Tornado – Резольвер ● tornado.netutil.BlockingResolver – Используется по умолчанию – Использует синхронный getaddrinfo – Не кеширует результаты – Обращение к DNS при каждом HTTP запросе – Пока DNS сервер не ответил всё стоит
  • 29. Странности Tornado – Резольвер ● tornado.netutil.ThreadedResolver – Вызывает getaddrinfo в отдельном потоке python – Overhead на потоки: память, cpu, GIL – Работает но выглядит как костыль
  • 30. Странности Tornado – Резольвер ● Мы написали простой асинхронный резольвер для Tornado IOLoop – Только TCP – Только записи A и CNAME – Кеширование ответов DNS по TTL – Большинство преобразований делается без системных вызовов
  • 31. Странности Tornado – HTTPClient ● HTTPClient создаёт не больше 10 исходящих соединений по умолчанию ● HTTPClient умеет стримить ответ сервера только если ответ chunked
  • 32. Странности Tornado ● Документация зачастую избегает описывать узкие места ● Будьте готовы читать исходный код tornado чтобы понять поведение системы
  • 33. Странности Python ● Сторонние библиотеки с нативным кодом текут и валят приложение через одну ● Найти утечку памяти в нативном коде крайне сложно ● Встроенная библиотеку xml.etree может приводить к SEGFAULT, мы используем lxml ● Сложные регулярные выражения могут остановить приложение busy-wait
  • 34. tornado/python в production MONIT – Убивает рабочие процессы если они выедают CPU – Убивает рабочие процессы если они превысили лимит по памяти – Стартует рабочие процессы если те умерли сами или были убиты – Простой и удобный web интерфейс
  • 35. tornado/python в production HAPROXY – Раскидывает приходящие запросы по доступным рабочим процессам – Балансирует нагрузку отправляя запросы к процессам с наименьшим количеством активных соединений – Адски быстрый и простой – Простой и удобный веб интерфейс
  • 36. tornado/python в production BENCHMARKS – Тотальное логирование времени выполения участков кода – Визуализация бенчмарков на видном месте – Немедленная реакция на аномалии в скорости ответов сервера
  • 37. Что делать с ожиданием ответов SQL сервера
  • 38. Удалённый сервер DB request response worker remote db parse request load value build response recv(syscall) send(syscall)
  • 39. Файловое key-value хранилище ● Содержимое файла должно быть смаплено в адресное пространство процесса mmap ● Рабочий обьём должен умещаться в оперативной памяти ● База должна позволять нескольким процессам одновременно читать данные без блокировок ● Мы используем kyoto cabinet и он прекрасен
  • 40. Быстрее чем redis и memcached worker load value Плюсы ● Не нужен внешний сервер ● Непревзойдённая скорость ● Не нужно переключать контекст и делать syscall ● Высокая отказоустойчивость
  • 41. Быстрее чем redis и memcached worker load value Минусы ● Медленный update данных ● Избыточность при работе в кластере ● Работает только для небольшого кол-ва данных
  • 43. Используйте потоковую обработку для разбора XML ● Опция streaming_callback у AsyncHTTPClient fetch позволяет получать данные по мере поступления ● Метод lxml.etree.XMLParser.feed позволяет парсить xml по кускам ● Если и это не помогает, делаем IOLoop.instance().add_timeout(time()) чтобы разбить поток исполнения
  • 44. tornado/python в production Приоритеты ● У разных запросов разные требования к скорости ответ ● Рабочие процессы привязываются к одной или нескольким группа приоритета ● Haproxy отправляет запросы в соответствующую группу рабочих процессов