Nginx против oProxy: друг другу сливаем :)


Потестировал производительность проксирования 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. #1 by tuupic on February 2nd, 2009

    А зачем в nginx 16 воркеров? Какие результаты с одним воркером в nginx ?

    • #2 by John Lepikhin on February 2nd, 2009

      16 рабочих там просто так. Потому что перед этим выставлял такую конфигурацию в oProxy. На производительность это абсолютно никак не влияет. Утилизация процессора на спящих процессах стремится к нулю. Результат с двумя рабочими (на машине 2 ядра) ровно такой же.

  2. #3 by Stas on February 5th, 2009

    И всё-таки, когда можно будет прочитать о релизе? :)

    • #4 by John Lepikhin on February 8th, 2009

      Релиз будет готов, когда всё будет готово, и не ранее :) Впрочем, до запуска в продакшен ничего дописывать конкретно в проксю уже не собираюсь. После — надо будет обязательно переписать на epoll. Исследовал вопрос, без этого никак.

  3. #5 by RedChrom on February 6th, 2009

    А может ты зареквестируешь добавление блога в planet.defun.ru ? Будет больше комментаторов :)

    • #6 by John Lepikhin on February 8th, 2009

      Пока желания нет. Заметная доля мотивации ведения блога — для себя.

(will not be published)

  1. No trackbacks yet.