Потестировал производительность проксирования HTTP трафика. Результаты местами получились весьма неожиданными.
Повторю, тестировалось именно проксирование. Известно, что при прямой отдаче и Apache, и Nginx использует ядрёный вызов sendfile(), который отдаёт содержимое файлика в сокет без лишних копирований. Это неинтересно. А вот проксирование — это совсем другое дело. В ядре пока что ещё нет прямых путей для копирования из сокета в сокет (есть полупрямой вариант splice() + pipe(), но как выяснилось он даже не на всех современных ядрах работает).
Итак…
На порту 8080 живёт Apache 2 ITK. У него в VirtualHost лежит bigfile размером ровно 20MB.
На порту 8081 живёт Nginx, который проксирует в Apache. Его конфиг:
worker_processes 16;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nodelay on;
gzip off;
server {
listen 12.34.56.78:8081;
server_name test1.com www.test1.com;
location / {
proxy_pass http://12.34.56.78:8080;
proxy_redirect http://test1.com:8080/ /;
proxy_set_header Host $host;
}
}
}
Результаты siege для Nginx:
debian2:~# siege -t30s -b -c 10 http://test1.com:8081/bigfile >/dev/null
** SIEGE 2.66
** Preparing 10 concurrent users for battle.
The server is now under siege…
Lifting the server siege… done.
Transactions: 372 hits
Availability: 100.00 %
Elapsed time: 29.66 secs
Data transferred: 6773.34 MB
Response time: 0.78 secs
Transaction rate: 12.54 trans/sec
Throughput: 228.37 MB/sec
Concurrency: 9.82
Successful transactions: 372
Failed transactions: 0
Longest transaction: 4.09
Shortest transaction: 0.07
228MB в секунду. Конкурентность 9.82. Доступность 100%. Самый медленный ответ: через 4 секунды.
Результаты oProxy (тоже 16 рабочих, чтобы было абсолютно честно):
debian2:~# siege -t30s -b -c 10 http://test1.com/bigfile >/dev/null
** SIEGE 2.66
** Preparing 10 concurrent users for battle.
The server is now under siege…
Lifting the server siege… done.
Transactions: 691 hits
Availability: 100.00 %
Elapsed time: 29.71 secs
Data transferred: 13820.00 MB
Response time: 0.38 secs
Transaction rate: 23.26 trans/sec
Throughput: 465.16 MB/sec
Concurrency: 8.94
Successful transactions: 691
Failed transactions: 0
Longest transaction: 9.18
Shortest transaction: 0.05
465MB в секунду (лучше более, чем в 2 раза). Конкурентность 9.18. Доступность 100%. Самый медленный ответ: через 9 секунд (хуже более, чем в 2 раза). Почувствуйте разницу ©
Мерим на маленьком файле. smallfile имеет размер 5 байт. Эмулируем атаку яростных 10 пользователей. Прочая конфигурация такая же. Результаты в Nginx:
debian2:~# siege -t30s -b -c 10 http://test1.com:8081/smallfile >/dev/null
** SIEGE 2.66
** Preparing 10 concurrent users for battle.
The server is now under siege…
Lifting the server siege… done.
Transactions: 16952 hits
Availability: 100.00 %
Elapsed time: 30.47 secs
Data transferred: 0.08 MB
Response time: 0.02 secs
Transaction rate: 556.35 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 9.97
Successful transactions: 16952
Failed transactions: 0
Longest transaction: 0.20
Shortest transaction: 0.00
Результаты в oProxy:
debian2:~# siege -t30s -b -c 10 http://test1.com/smallfile >/dev/null
** SIEGE 2.66
** Preparing 10 concurrent users for battle.
The server is now under siege…
Lifting the server siege… done.
Transactions: 8718 hits
Availability: 100.00 %
Elapsed time: 29.57 secs
Data transferred: 0.04 MB
Response time: 0.03 secs
Transaction rate: 294.83 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 9.27
Successful transactions: 8718
Failed transactions: 0
Longest transaction: 9.00
Shortest transaction: 0.00
А вот тут сливаем, почти в 2 раза. Аналогичная картина при увеличении конкурентных запросов. Но прокся при этом начинает показывать ещё более худшие результаты в Longext transaction. Буду над этим работать.
Update: нашёл в чём причина. В генах архитектуре. Завтра найду время, и перееду с socket passing на shared accept() и, возможно, epoll. Правда, при этом не совсем понятно, что делать с шедулингом нагрузки по рабочим. Рычаг теряю. Судя по логам, accept() на каждое соединение в среднем 3 миллисекунды тратит. Отсюда и цифра — 300 транзакций в секунду.
#1 by tuupic on February 2nd, 2009
А зачем в nginx 16 воркеров? Какие результаты с одним воркером в nginx ?
#2 by John Lepikhin on February 2nd, 2009
16 рабочих там просто так. Потому что перед этим выставлял такую конфигурацию в oProxy. На производительность это абсолютно никак не влияет. Утилизация процессора на спящих процессах стремится к нулю. Результат с двумя рабочими (на машине 2 ядра) ровно такой же.
#3 by Stas on February 5th, 2009
И всё-таки, когда можно будет прочитать о релизе? :)
#4 by John Lepikhin on February 8th, 2009
Релиз будет готов, когда всё будет готово, и не ранее :) Впрочем, до запуска в продакшен ничего дописывать конкретно в проксю уже не собираюсь. После — надо будет обязательно переписать на epoll. Исследовал вопрос, без этого никак.
#5 by RedChrom on February 6th, 2009
А может ты зареквестируешь добавление блога в planet.defun.ru ? Будет больше комментаторов :)
#6 by John Lepikhin on February 8th, 2009
Пока желания нет. Заметная доля мотивации ведения блога — для себя.