Комментарии 40
Вообще говоря, немного неожиданный результат для nginx. Я предполагал что nginx (ну и HAProxy, возможно), будет далеко впереди. А не пробовали поставить их всех без Docker?
А Caddy сам пошёл за сертификатами в LE? В какой момент?
С год назад выбирал прокси для Docker Swarm. В первую очередь нужна была гибкость и разные настройки. nginx я люблю, но подкупила реклама Traefik о том, что сам может обнаруживать смену конфигурации апстримов кластера. Envoy и Caddy что-то показались туповатыми с точки зрения конфигов. Traefik, честно говоря, тоже, но кое-как смог его завести. В итоге очень не нравится, серьёзно думаю поменять на nginx. Производительность не очень интересовала - у меня не такие большие нагрузки.
Caddy сам ходит за сертами на основе Caddyfile, в момент запуска docker compose
Без Docker, с тем же Caddy или Nginx, результаты лучше процентов на 5
А что касается результатов, как я уже писал, возможно с помощью грамотного тюнинга можно выжать и больше, но из коробки увы, мы сами удивились ))
Для Swarm плохи все прокси, основанные на файлах конфигов. Пришлось пилить свой на лейблах и событиях Докера, без редеплоя.
Любопытно, а можете показать что у вас получилось? Или хотя бы рассказать поподробнее?
Судя по логам Traefik, он не использует события докера, а раз в несколько секунд перечитывает весь список контейнеров. Ну, либо в логи зачем-то слишком (слишком!) часто пишет о том что нашёл изменения. Это мне в нём тоже не нравится.
В принципе, у меня есть вариант использовать nginx и резолвер докера, а для динамической смены конфига без редеплоя - хранить его в Redis и обновлять через Lua (upstreams).
nginx 1.27.3
в директиву server, используемую в блоке upstream, добавлена поддержка параметра resolve, включающего отслеживание изменения IP-адреса для используемого доменного имени и автоматическое обновление конфигурации блока upstream без необходимости перезапуска nginx в случае изменения адреса;
Вдохновил https://github.com/lucaslorentz/caddy-docker-proxy но решил сделать надёжнее и без файлов. Осталось прикрутить TLS и mTLS.
С гибкостью и разными настройками у Envoy всë в порядке. Просто его формат конфигов определяется схемой на Protobuf. Это следствие того, что основной use case для Envoy - динамическое переконфигурирование на лету. Файл конфига, который указывается при старте - это просто bootstrap конфиг, который чаще всего просто подсказывает, где брать остальное - внешние процессы, знающие текущее состояние кластера (Cluster Discovery Service), роуты (Routes Discovery Service) и прочие xDS. Это причина, по которой именно на Envoy довольно часто строят сервисмэши, ингресс-контроллеры и API- гейтвеи. Не надо из темплейтов генерить файлы конфигов...
Ну так-то понятно - динамическая переконфигурация и нужна от всех. Вопрос лишь в том, где описывать тот же список сервисов и их личный роутинг с особенностями (routes, rewrite, авторизация и тп).
Traefik пытается брать всё из labels, но не всегда получается через них это задать.
nginx может всё и даже больше, но ему нужен конфиг, который, в принципе, можно генерировать и подсовывать прямо в контейнер для hot reload. Однако, на каждый новый контейнер это немного не динамически, да.
Спасибо за отличную стать Интересно было бы посмотреть результаты тестирования http2/grpc
А как Вам Angie поможет заменить NPM? Это же вроде как троллейбус буханкой белого хлеба заменять, если вы понимаете о чем я.
Есть подозрения, что у Angie будут результаты такие же или хуже чем у Nginx, из-за количества дополнительных модулей в стандартной сборке.
Есть подозрения
Ну подозрение подозрениями, а вот тесты бы дали фактические результаты.
А как Вам Angie поможет заменить NPM?
И то и другое можно использовать в качестве реверсивного прокси, и то и другое умеет работать с LetsEncrypt, отличие в том, что NPN, являясь надстройкой над nginx имеем веб интерфейс для настройки сайтов (в что можно и лучше перенести на CI/CD), но не имеет никаким вменяемых мониторингов.
В моем случае, я не знаю зачем, но дома имею
некоторую домашнюю сетевую лабу с несколькими мини ПК на проксмоксе
одноплатник с NPN
роутер, с dnat www трафика на NPN и локальным DNS
Ряд сервисов (42 хоста), которые идут на NPM, а он уже стучится виртуалки и контейнеры внутри кластера.
Хочу: запустить кластер из реверс прокси, как минимум добавить по 1 экземпляру на каждом инстансе PVE, в локальном dns прописать для DNS имени не одноплатник, а проксик, находящийся на одном физическом хосте с сервисов, чтобы по локальной сети меньше гонять трафика. Как минимум вариант с конфигом в гите и деплоем на несколько машин выглядит решением
А что такое NPM/NPN?
Мои знания ограничиваются на https://www.npmjs.com/ как NPM и NPN/ALPN как NPN
Это Nginx Proxy Manager - попытка приделать веб-интерфейс к nginx, чтобы .. Непонятно чтобы что, но, наверное, кому-то проще кликать мышкой и не запоминать конфиг, хотя мне сложно представить чтобы это хоть как-то было близко к функционалу текстовых конфигов.
Я рекомендую его для несисадминов ну и сам использую в некоторых местах, на самом деле, проще накликать мышкой базовую конфигурацию для какого-то внутреннего сервиса: вбиваешь доменное имя, хост и порт бэкенда, по желанию выбираешь в списке wildcard ssl сертификат, можешь выбрать в списке правила безопасности - ошибиться с настройкой неподготовленному специалисту значительно сложнее, нежели при работе с конфигами напрямую.
"Сырой конфиг" тоже можно вставить, но NPN это не для извращений в конфигах, а для, например, недавнего варианта: настроил в контейнере свой nginx, там сложные правила, работа как с локальным кешем, так и с api бэком, все по классике, в общем. Далее, зашел в веб интерфейс и прописал, что по https://notes.mydomain.tld хостится на http://notes.lan и все
Ну и в плюсы NPM можно занести отличную работу в докере, новичок не всегда завернет nginx и certbot в docker-compose.yml с первой попытки, а тут полностью прозрачная работа с сертификатами, как это есть у конкурентов типа caddy
Nginx unit хорошо бы ещё..
Вот так вот, натестируют по 1й минуте, а потом на проде "ой, а у нас тут фигня какая-то"
Господа, делайте проверки длительными, система себя проявляет когда все кэш области забиваются и вот там проявляется архитектура.
Когда я говорю длительными, я имею в виду часы, дни. Мы испытываем системы неделями и открываем много нового для себя а иногда и для производителя.
А можно на примерах поподробнее? И вообще есть ли в этом смысл если релизы чаще раза в неделю (прокси можно рестартить по очереди)?
У нас нт проводится 12 часов. Большое количество проблем возникает в промежутках с 4 до 8 часов работы. Условно в первые 4х часа работает стабильно, если же 8+ то уже дальше всё стабильно . Причины самые невероятные возникали (кеши, коннекшены к базе, утечки памяти, подвисшие потоки и тд). Так что нт важно проводить в течении длительного времени. Особенно в высоконагруженных системах.
Спасибо за пост. Можете выложить результаты в виде таблицы?
Сам использую haproxy, от nginx отказался давно уже, простота конфигурации на haproxy подкупила. С 2.8 в связке с acme обновляет сертификаты без перезапуска, появился quic, не назвал бы его там готовым к проду, но оно работает и в целом quic внутри страны ходит исправно, в 3.0 версии добавили сохранение статистики и доработали quic, должен выйти 3.1 lts где quic довели до ума. И есть экспортер Prometheus в коробке, что куда проще чем с nginx, одна строка в frontend и пошли метрики.
Полезная нагрузка в виде "hello world" - не сказать что эталон по объему ответа. Результаты могли исказиться так или иначе - служебного трафика сильно больше полезного.
Но тут тогда сразу и разный объем ответа просится на тестирование - чтобы выявить разницу при разных объемах ответа. Что удлинит тест в разы.
А не пробовали сразу Golang-сервис запустить с HTTPS? Т.е. без обратного прокси. Как отправная точка тоже было бы полезно (помимо голого HTTP). Правда тогда бекенд тоже с 32 vCPU и 128 ГБ RAM надо было бы запускать...
Можете протестировать с таким конфигм nginx? Есть гипотеза что вся разница между проксирующими серверами свелась к включенному или выключенному keepalive по умолчанию. Как следствие - заканчиваются эфемерные порты и такое большое время на обработку и так много фейлов.
http {
upstream backend {
server 10.0.0.4:8080;
keepalive 4;
}
server {
listen 443 ssl;
server_name test-backend.mish.design;
ssl_certificate /etc/letsencrypt/live/test-backend.mish.design/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test-backend.mish.design/privkey.pem;
location / {
proxy_pass http://backend;
proxy_set_header Connection '';
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Очень странный результат для nginx. Надеюсь, дело в неправильных настройках (как выше написали про keepalive).
Зачем включили multi_accept? Он выключен по умолчанию не просто так. Это лучший способ вызвать дисбаланс в бенчмарке. Скорее всего у вас большинство соединений в итоге приняли и обрабатывали всего несколько первых рабочих процессов. От того и такие результаты...
Что в логе ошибок было? nginx пишет обычно что пошло не так... возможно у вас закончились дескрипторы или уперлись в лимит как раз из-за multi_accept.
Перед тем, как тестировать, выровняли ли настройки TLS-шифрования? У nginx по умолчанию `ssl_ciphers HIGH:!aNULL:!MD5;`. У других серверов скорее всего шифрование использовалось более слабое и менее ресурсоемкое, так что CPU не стал для них бутылочным горлышком.
Одинаковы ли у серверов настройки логирования?
Крайне предвзятый тест, без попытки разобраться в причинах и изначально неравными настройками.
Моя гипотеза: из-за "multi_accept" соединения между рабочими процессами распределялись крайне неравномерно, а из-за тяжелой криптографии рабочие процессы, набрав соединения, заблокировались на CPU.
Затем и включили, что без него только хуже)
Результаты разных комбинаций добавил в статью
Настройки TLS выровняли в последнем тесте + включенный multi_accept - результаты стали немного получше, но увы до Envoy или HAProxy - очень и очень далеко
Какие ошибки в логах? Во всех тестах, что мы проводили на моей памяти, haproxy оказывался чуть хуже nginx, да в общем-то неоткуда там разнице особой взяться, тем более в разы - архитектура очень похожа. Поэтому есть все основания полагать, что что-то фундаментально не так с конкретной установкой nginx. Что все же в логах ошибок? И сам nginx, кстати, откуда? Из официального репозитория на `nginx.org`?
И кстати, ни один из серверов сам не обрабатывает TLS - эту задачу решают TLS-библиотеки. Учитывая, как изменились результаты с настройкой ssl_ciphers
, возможно вы на самом деле протестировали производительность сборок конкретных библиотек. Для равноценного теста с участием TLS - сервера должны быть собраны с одной и той же библиотекой.
Если интересно все же разобрать в причинах, я бы предложил попробовать повторить тест без TLS в принципе. Если результаты nginx и haproxy окажутся в этом случае близки, то дальше нужно будет разбираться, а что не так с TLS.
И обращаю также внимание на то, что у nginx по умолчанию включен `access_log`, а у того же haproxy, насколько я помню, его нужно включать принудительно.
> Затем и включили, что без него только хуже)
По вашим данным с выключенным multi_accept число успешных запросов больше:checks_succeeded...................: 30.91% 312910 out of 1012194 checks_failed......................: 69.08% 699284 out of 1012194
против с включенным: checks_succeeded...................: 25.90% 244664 out of 944528 checks_failed......................: 74.09% 699864 out of 944528
или я неправильно интерпертирую данные?
Но должно быть вообще 100%. То, что nginx теряет запросы - это что-то ненормальное, в error_log должны быть причины этому.
Изначально цель статьи была — сравнить производительность “из коробки”, с минимальными настройками, что и было сделано.
Также я упомянул, что для nginx требуется дополнительный тюнинг.
Понятно, что нюансов масса. Если у вас, как у бывшего разработчика ядра nginx, есть понимание, как быстро и эффективно настроить nginx для обработки 50k RPS — будет круто, если поделитесь рабочим конфигом. Думаю, сообщество будет только благодарно.
Мое понимание заключается в том, что nginx из коробки не должен проигрывать haproxy в разы. Указанное число RPS для сервера с 32 CPU - это вообще крайне мало... и выглядит очень подозрительно.
Жаль, если вы не хотите разобраться в причинах наблюдаемого явления. Даже если я попрошу воспроизвести коллег, то с большой вероятностью у нас не получатся такие же цифры, т.к. не получится точно повторить указанный стенд.
Вопрос, у вас HTTPS соединения keepalive или на каждый запрос новое? А если на каждый запрос новое соединение, то используется ли возобновление TLS-сессий и каким механизмом? Полный хендшейк - это весьма CPU-нагруженная операция, и лишь разница в настройках TLS-сессий может полностью перевернуть картину между серверами. Опять же, каждая настройка хороша под конкретный стенд, поэтому выравнивать сервера по настройкам, тем более таким критичным, как TLS - необходимо, иначе будет просто необъективный результат, который применим только к конкретному стенду, а на другом стенде будет совсем другим. Так вы протестировали сервера на то, как их настройки по умолчанию подходят для вашего стенда и это будет иметь мало общего с производительностью в реальности, даже на тех же настройках - просто в силу того, что клиенты обычно не ведут себя как отдельно взятый тестовый стенд.
У haproxy, кстати, по умолчанию включен кэш SSL-сессий, а у nginx он выключен. И если клиент, например, не умеет в сессионные тикеты, то вот и разница - тогда в одном случае вы считаете полные хендшейки, а в другом возобновления сессий.
50k RPS для nginx - это вообще пустяки, но вот криптография, которой занимается TLS-библиотека - она может стать лимитирующим фактором. К примеру, вот такой sizing guide для nginx plus: https://www.f5.com/pdf/deployment-guide/Sizing-Guide-for-Deploying-NGINX-Plus-on-Bare-Metal-Servers-2019-11-09.pdf - он уже старенький, ещё от 2019 года, но можно заметить, что на 32 CPU легко может быть 1 000 000 RPS, но всего около 50к полных хендшейков.
Спасибо да статью!
А если использовать режим network_mode: host ?
Надо бы указывать версии продуктов.
haproxy 3.1.6
envoy 1.34.0-dev
nginx 1.27.4
traeffik 3.3.5
caddy 2.9.1
P.s. Добавил и в начало статьи
еще важна реализация SSL
haproxy и nginx по умолчанию билдятся с openssl 3.x (и у разработчиков haproxy есть претензии к производительности настолько что дают совет "не используйте openssl3 - используйте альтернативы, причем nginx меньше подвержен)
envoy использует boringssl - форк openssl 1.x еще до этих проблем
traeffik и caddy - не использовал, поэтому не стал закапываться.. какую-то гошную реализацию tls судя по всему
В итоге мало того что конфигурационные значения по умолчанию у всех проксей разные, есть еще внешние зависимости.
Имхо надо разделять тестирование чисто по http - оно бОльше скажет о производительности самой прокси(не учитывая проблему значений по умолчанию) и по https.
Проксирование из коробки: сравнительный анализ HAProxy, Envoy, Nginx, Caddy и Traefik