HAProxy vs. Pound
Некоторое время назад столкнулся с неприятным "притормаживанием" при выполнении запросов. Как выяснилось, проблема в реверс-прокси Pound - в режиме HTTPS его эффективность оказалась не слишком высокой. Трафик проекта, на котором это произошло, составляет около 200 Gb в месяц, или миллион "с гаком" запросов в сутки (весь трафик по протоколу HTTPS). Притом в режиме HTTP (по отзывам разработчиков в рассылке AOLServer) Pound выдерживает до 800 запросов в секунду (ну, правда, неизвестно, на каком железе), после чего приходится ставить другой прокси.
В качестве альтернативы выбрал HAProxy - и код понравился, и автор помог перенести конфиг Pound. Также оказалось очень полезным, что автор HAProxy написал патч к Stunnel4 для поддержки хидера X-forwarded-For (этот патч понадобилось немного адаптировать к версии stunnel4 в debian lenny, результат можно взять на сайте HAProxy или уже собранный пакет Stunnel4 в моем репозитории). Что приятно, после замены реверс-прокси в top-е его практически не видно, иногда заметен stunnel, но в общем и целом производительность связки HAProxy+Stunnel4 как минимум на порядок выше. Для поддержки условных редиректов следует обновить HAProxy, да и автор советовал, так что собрал пакет с последней версией, которая меня и устроила (брать все в том же репозитории).
В качестве альтернативы выбрал HAProxy - и код понравился, и автор помог перенести конфиг Pound. Также оказалось очень полезным, что автор HAProxy написал патч к Stunnel4 для поддержки хидера X-forwarded-For (этот патч понадобилось немного адаптировать к версии stunnel4 в debian lenny, результат можно взять на сайте HAProxy или уже собранный пакет Stunnel4 в моем репозитории). Что приятно, после замены реверс-прокси в top-е его практически не видно, иногда заметен stunnel, но в общем и целом производительность связки HAProxy+Stunnel4 как минимум на порядок выше. Для поддержки условных редиректов следует обновить HAProxy, да и автор советовал, так что собрал пакет с последней версией, которая меня и устроила (брать все в том же репозитории).
Comments
Что касается nginx на продакшене... видел я сервера, которые при DDOS дохнут, ибо nginx забивает логи ошибок со скоростью много мегабайт в секунду - во-первых, создавая LA>100, во-вторых, занимая весь /var/log. В то время как нормальный реверс-прокси, в отличие от, вообще во время работы не имеет доступа к жесткому диску. Так что nginx по своей идеологии уже явно не секьюрное и не надежное решение. Его применение может быть оправдано, только если бэкендом стоит монстр вроде апач, который и статику нормально отдать не умеет, и динамику обрабатывает, потребляя жуткое количество ресурсов.
По тестам производительности nginx серьезно уступает специализированным решениям, таким, как HAProxy.
2. Уровень логгирования ошибок можно менять. Если ставить error или crit то сообщений в error_log будет мало. Если поставить info то разумеется сервак от DOS умрет, хотя при небольшой нагрузке будет работать нормально. Можно вообще error_log отключить.
3. Тесты бывают очень разные и сильно зависит от того кто и как эти тесты проводил. К тому же nginx позволяет часть функциональности вынести с бэкенда на фронтенд, что часто бывает удобно.
2. Логирование должно выполняться стандартными средствами syslog. Доступ реверс-прокси к диску - уже потенциальная дыра в безопасности. Ориентация на виндоус-платформы, не имеющие syslog, отнюдь не аргумент - нет смысла запускать производительное серверное решение на "игрушечной" ОС.
3. Разделение на фронтенд и бэкенд для того и придумано, чтобы _разделить_ полномочия. А если часть функций бэкенда выполняет фронтэнд, то никакого выигрыша в уровне защиты, контроле доступа и эффективности не будет. Да, в качестве "костыля" к apache нередко используют nginx, но это проблемы apache. Полагаю более оправданным использовать сервер приложений, к которому не требуются "костыли".
Что касается функционала - HAProxy умеет
- балансировать запросы между серверами на основе application-defined cookie (вроде бы nginx так тоже может, но требует сборки с perl),
- управлять очередью "ожидающих" запросов (насколько мне известно, nginx просто не принимает "лишние" соединения),
- использовать различные алгоритмы балансировки,
- предоставляет веб-интерфейс для простмотра и сбора (в формате CSV) статистики,
- не обращается к жесткому диску (nginx создает временные файлы для загружаемых файлов, пишет логи и т.п.)
Тесты смотрите здесь. Замечу лишь, что уже при 30-ти одновременных сессиях HAProxy в разы превосходит nginx. Меня же интересуют как минимум сотни одновременных сессий (на бэкендах стоит AOLServer, каждый экземпляр которого способен обрабатывать сотни одновременных сессий, т.е. тысячи запросов в секунду).
2. логгирование через syslog возможно только при маленькой нагрузки. Попробуйте писать 1000 строчек в секунду (для access_log если его писать будет минимум одна строчка на запрос) в файл и через syslog и в top легко увидите разницу.
2. У меня access.log порядка гигабайта в сутки, "в пике" нагрузки это около полтысячи запросов в секунду. В выводе top я ни разу не видел rsyslog в верхних строчках. Диски - 2 SATA в зеркале. Да, логирование настроено асинхронное, но это как бы само собой подразумевается. Что я делаю не так?
2. Как минимум при использовании syslog больше переключений контекста (при записи в файл - один syscal на запись строчки в лог, при записи через syslog - минимум три - sendto, recvfrom, write, реально их еще больше, и еще данные два раза копируются из userspace в ядро и обратно). Все это конечно недорогие операции, но не бесплатные. Не знаю как в Linux, но под FreeBSD можно заметить небольшую разницу в %idle при использовании syslog и прямой записью в файл (сам syslog при этом в верхних строчках top-а не появляется).
Что касается применения конечного автомата в nginx, то это, конечно, техническое преимущество nginx перед apache, но от перегруженности функционалом не спасает. А поскольку речь идет о выборе между HAProxy и nginx, то более отлаженный код и обеспечивает более эффективную реализацию (оба они event-driven, только HAProxy запускает лишь один процесс, а nginx - несколько).
2. "Небольшая разница" в количестве тактов процессора заведомо окупается меньшей нагрузкой на дисковую подсистему (напомню, nginx временные файлы создает для пересылаемых данных), большей безопасностью и надежностью, а также удобством настройки через стандартный syslog. Причем последний может писать как в файлы, так и в БД или на удаленную машину (и не только), причем предоставляет различные виды буфферизации вывода. Думаю, не стоит и говорить, что оптимизация дисковых операций для нагруженной системы - важнейшая из задач.
что касается нескольких процессов - они нужны для того, чтобы:
- соединения могли обрабатывать не привилигированные процессы (workers), но при этом был рутовый процесс (master) для того чтобы делать bind на порт < 1024 и создавать log-файлы.
- несколько воркеров нужно чтобы использовать несколько CPU. Просто одного процесса недостаточно, либо он должен быть тредовый (что усложняет отладку поскольку чревато разными race).
nginx пишет проксируемые данные во временные файлы только для ответов, больше заданного в конфиге размера, и их создание можно отключить (тогда бэкенду придется ждать пока клиент заберет ответ).
В nginx многое настроить можно, но его модель безопасности - это идеология веб-сервера, а не защищенного прокси. Не говоря о том, что мало смысла заниматься настройкой лишь для отключения абсолютно всех "наворотов" эдакого комбайна, когда есть компактные решения без "лишних деталей".
А кроме ответов, есть еще и сами запросы, тело которых nginx тоже пишет в файл. Согласен, это может облегчить жизнь "нерадивому" бэкенду, но ведь костыль же. Если бэкендом стоит AOLServer, или эрланговский веб-сервер или другое полнофункциональное решение, все эти "довески" nginx можно убрать и забыть о них навсегда. В таком случае реверс-прокси - всего лишь балансировщик, не более того, а вот как раз балансировку nginx и не умеет (ну, за исключением одного-единственного алгоритма).
С другой стороны, nginx может оказаться истинным спасением для системного администратора, у которого целый зоопарк веб-проектов (возможно, на разных веб-серверах) со всяческими php-форумами и проч., сжирающими все ресурсы сервера при нескольких одновременных подключениях, и надо как-то все это хозяйство поддерживать. Сам видел, что в таких ситуациях nginx бывает незаменим. Но с точки зрения архитектуры получается полный бардак. При использовании же узкоспециализированного решения, например, Pound или HAProxy, бэкенды должны уметь качественно работать самостоятельно.
Надеюсь, мне удалось изложить мой взгляд на "экологическую нишу" обитания nginx. Имхо появление nginx - результат использования "кривых" веб-серверов и очень низкого качества веб-проектов. Да, nginx помогает облегчать ситуацию, но суть проблемы он не решает и решить не может, т.к. проблема отнюдь не технического характера. Хотелось бы все же, чтобы разработчики старались делать проекты так, чтобы админам не было необходимости прибегать к помощи nginx.
А еще забавно, что сайт aolserver.com работает под nginx :)
# Tuning options
ns_param maxconnections 100 ;# Max connections to put on queue
ns_param maxthreads 100 ;# Tune this to scale your server
ns_param minthreads 10 ;# Tune this to scale your server
Т.е. обрабатывать 100 запросов в каждом треде (последовательно), одновременно выполнять от 10 до 100 тредов. Полагая среднее время обработки запроса равным 100 мс (при использовании пула подключений к PostgreSQL примерно так и выходит), при 100 тредах можно обрабатывать 1000 запросов в секунду на каждом бэкенде. И вовсе ни к чему создавать 1000 тредов, а тем более тратить ресурсы на их создание/удаление (разработчики AOLServer рекомендуют обрабатывать от 1000 и более запросов в каждом треде, при этом треды работают еще эффективнее). При использовании СУБД SQLite обработка запроса с несколькими обращениями к БД занимает всего лишь около 12 мс (на полной рабочей базе, сконвертированной из постгреса в эскулайт), а в таком случае и 20-ти тредов хватит.