Задача очень простая, вроде бы:
- Нужно реализовать HTTP-сервер
- На него будут приходить простые GET-запросы вида http://x.x.x.x/?a=1&b=2
- В процессе обработки запроса нужно будет сделать ряд запросов к MySQL, обработать их результаты простой if{}else{} логикой и отдать ответ.
- Язык не важен
- Каждый запрос должен гарантированно выполниться за 1-2 секунды
Петрушка в том, что запросов одновременно может приходить много, на данный момент чуть меньше тысячи в секунду, потенциально - больше, поэтому хочется запас. И выполняться каждый запрос, потенциально, может 100-200мсек.
Что пробовал:
- Банальный nginx + php-fpm. После долгого насилия над конфигами этих двух софтин, MySQL и sysctl.conf оно кое-как научилось держать 1000 одновременных коннектов, при этом php-fpm форкнул, соответственно, 1000 воркеров и сожрал 13Гб памяти. Как-то, мягко говоря, не оптимально. При этом при тестах через wrk и ab были таймауты в процессе получения URL, но они скорее всего связаны с MySQL. Тестил простым скриптом типа (подключиться к mysql, select столбец from table с двумя строками, print столбец, отключиться от mysql).
- nodejs. Оно однопоточное, поэтому особого толку нет, плюс всякие непонятные глюки - в начале теста идёт ровно, под конец сервер дико напрягается ksoftirq и нода падает с ошибкой в духе «too many open files». Либо глючт mysql-модуль, коих там море в ноде и все разной степени кривзины, либо ещё что... разбираться лень. Скорость, в любом случае, достаточно низкая. Скрипт аналогичный.
- Perl в виде PSGI приложения и разных серверов для его исполнения, как форкающихся (starman), так и на базе event loop (twiggy). Форкающиеся работали хорошо, но проблемы аналогичные php-fpm - каждый форк жрёт кучу памяти. event-овые опять таки однопоточные, да и доступ в SQL их блокирует.
- Python + twisted. Оно event-овое, один поток. Проблемы аналогичные.
В результате пришёл к выводу, что мне нужно что-то тредовое т.к. каждый запрос к SQL выполняется какое-то время и если использовать event loop реализации - блокирует остальных. Форкающиеся сервера хороши, но памяти жрут мама не горюй.
Можно, конечно, написать свой HTTP-сервер с тредами и танцовщицами, на том же перле, но велосипед изобретать не хочется. Есть перл-модуль HTTP::Daemon::Threaded, но я его пока что-то не до конца осилил. Всякие apache+mpm_worker+mod_perl пока не смотрел, но выглядит достаточно вкусно.
Может я чего-то элементарного не вижу? Или просто дохрена хочу?