NGINX Прокси Реверса HTTPS - Быстрый TTFB, но низкий параллелизм

У меня есть приложение, которое работает: NGINX (SSL) => ЛАК (КЭШ) => APACHE/PHP.

Выполняя ab сравнительный тест, я могу достигнуть 30k + запросы / второй на слое лака (через HTTP) через экземпляр EC2 t2.small. Однако, когда я запускаю тест через NGINX (HTTPS), я только могу продвинуть 160 запросов / второй (среднее число 43 мс для TTFB от государственной сети).

nginx.conf

user  nginx;
worker_processes  auto;

worker_rlimit_nofile 65535;

error_log  /var/log/nginx/error.log;

pid        /var/run/nginx.pid;


events {
    worker_connections  16024;
        multi_accept on;
}

и на http уровне:

sendfile        on;
tcp_nopush     on;

keepalive_timeout  10;


ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

domain.conf

server {
        listen 443 ssl;

        server_name xyz.com;
        ssl_certificate /home/st/ssl3/xyz.crt;
        ssl_certificate_key /home/xyz/ssl3/xyz.key;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

        ssl_session_tickets on;

        location / {

                proxy_buffers 8 8k;
                proxy_buffer_size 2k;


            proxy_pass http://127.0.0.1:79;
            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 https;
            proxy_set_header X-Forwarded-Port 443;
            proxy_set_header Host $host;

                proxy_redirect off;

        }

    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
}

Вот сравнительный тест для Apache непосредственно

ВНУТРЕННИЙ => @APACHE:

Concurrency Level:      10
Time taken for tests:   0.694 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Non-2xx responses:      1002
Keep-Alive requests:    996
Total transferred:      705122 bytes
HTML transferred:       401802 bytes
Requests per second:    1440.93 [#/sec] (mean)
Time per request:       6.940 [ms] (mean)
Time per request:       0.694 [ms] (mean, across all concurrent requests)
Transfer rate: 992.22 [Kbytes/sec] received

Вот сравнительный тест для Лака (он работал в 20-30k ранее - израсходовал мои циклы ЦП, средний ATM является 4-8k RPS),

ВНУТРЕННИЙ => @VARNISH => @APACHE:

Concurrency Level:      10
Time taken for tests:   0.232 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      23439800 bytes
HTML transferred:       23039412 bytes
Requests per second:    4310.16 [#/sec] (mean)
Time per request:       2.320 [ms] (mean)
Time per request:       0.232 [ms] (mean, across all concurrent requests)
Transfer rate:          98661.39 [Kbytes/sec] received

Вот сравнительный тест для NGINX через HTTP

ВНУТРЕННИЙ => @NGINX [HTTP] => @VARNISH => @APACHE:

Concurrency Level:      10
Time taken for tests:   0.082 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Non-2xx responses:      1001
Keep-Alive requests:    1000
Total transferred:      382382 bytes
HTML transferred:       184184 bytes
Requests per second:    12137.98 [#/sec] (mean)
Time per request:       0.824 [ms] (mean)
Time per request:       0.082 [ms] (mean, across all concurrent requests)
Transfer rate:          4532.57 [Kbytes/sec] received

Вот сравнительный тест для NGINX через HTTPS

ВНУТРЕННИЙ => @NGINX [HTTPS => HTTP] => @VARNISH => @APACHE:

Concurrency Level:      10
Time taken for tests:   7.029 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Non-2xx responses:      1000
Keep-Alive requests:    0
Total transferred:      663000 bytes
HTML transferred:       401000 bytes
Requests per second:    142.27 [#/sec] (mean)
Time per request:       70.288 [ms] (mean)
Time per request:       7.029 [ms] (mean, across all concurrent requests)
Transfer rate:          92.12 [Kbytes/sec] received
1
задан 24 June 2015 в 03:18
1 ответ

Ну, судя по информации, которую вы предоставили (и не предоставили), я могу только догадываться. Но судя по типу экземпляра (t2 имеет взрывную производительность, основанную на билетах, и при выходе из билетов получает около 20% от ядра; это не самый лучший экземпляр, на котором можно делать тесты) и использованию ab для тестирования (btw. Когда вы пишете это как 'AB тестирование', первое, что приходит на ум, это this), я бы сказал, что ваша производительность соответствует ожиданиям.

При запуске SSL, или TLS сеанса, наиболее интенсивной задачей с точки зрения производительности является не шифрование/дешифрование данных, а обмен ключами. Так как ab не использует SSL кэширование сеанса, обмен ключами должен осуществляться при каждом соединении.

В зависимости от используемого набора шифров/кексов/аутов (не могу сказать, нет ab предоставленного вывода), это может быть довольно большой работой для центрального процессора. А так как оба конца находятся на одной машине, вы удваиваете требования к процессору на одно соединение (это упрощение, но здесь достаточно хорошо).

В реальном использовании, keep alives может помочь вам получить лучшую производительность (зависит от клиента, обычные браузеры используют его; попробуйте ab -k). И вы получите лучшую производительность от кэширования SSL-сессий, о котором вы говорили (опять же зависит от клиента, обычные браузеры поддерживают его).

Есть несколько других способов, которые помогут вам улучшить вашу производительность. Конечно, вы можете получить лучшее аппаратное обеспечение. Вы можете оптимизировать размер ключей (зависит от уровня защиты, требуемого для приложения) - меньшие ключи обычно дешевле для работы. Тестирование на разных машинах может улучшить, а может и нет, кажущуюся производительность. А получение другой сборки OpenSSL или другой SSL-библиотеки в целом также может обеспечить лучшую производительность.

Просто для справки, вы можете взглянуть на эту статью от Intel. Они действительно сравнивают производительность на высокооптимизированной машине (и некоторых оптимизированных программах). Считайте, что у вас есть менее 1/30 их вычислительной мощности (может быть до 1/150, если у вас нет билетов).

Хотя, если вам нужен высокопроизводительный SSL, возможно, стоит подумать об использовании Amazon ELB для выполнения SSL-терминации за вас, так как вы уже на EC2.

Правка: Например Apache JMeter использует ssl контекстное кэширование. httperf также делает это. Особенно я нахожу JMeter хорошим в симуляции реальных нагрузок. Но для этого httperf способ кэширования сессии может работать лучше всего.

-k не видит никакой разницы с -k может быть потому, что он до сих пор не используется. Зависит от настроек параллелизма и (по крайней мере, от моей машины), похоже, также зависит от url. Она не использует keepalives, если я использую доменное имя, которое указывает на более чем один IP в url (не спрашивайте меня почему).

В зависимости от вашего восприятия массивности, но я бы не ожидал получить более 500 соединений в секунду в очередях на этом довольно маленьком экземпляре и не более 250 cps.

Сравнение лакового чистого текста http с nginx ssl - это сравнение груш с яблоками. Или скорее сравнение черники с арбузами с точки зрения требований к оборудованию.

Снова для справки (обратите внимание на строку Keep-Alive requests: 100).

Без -k

Concurrency Level:      1
Time taken for tests:   0.431 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      399300 bytes
HTML transferred:       381200 bytes
Requests per second:    232.26 [#/sec] (mean)
Time per request:       4.305 [ms] (mean)
Time per request:       4.305 [ms] (mean, across all concurrent requests)
Transfer rate:          905.69 [Kbytes/sec] received

С -k

Concurrency Level:      1
Time taken for tests:   0.131 seconds
Complete requests:      100
Failed requests:        0
Keep-Alive requests:    100
Total transferred:      402892 bytes
HTML transferred:       381200 bytes
Requests per second:    762.11 [#/sec] (mean)
Time per request:       1.312 [ms] (mean)
Time per request:       1.312 [ms] (mean, across all concurrent requests)
Transfer rate:          2998.53 [Kbytes/sec] received

Edit2: Ну, вы должны понять, что подача контента непосредственно из памяти (это то, что делает Varnish) настолько проста, насколько она может быть получена. Вы разбираете заголовки, находите содержимое в памяти, выплёвываете его. И Варниш превосходит в этом.

Установление зашифрованного соединения - это совершенно другой уровень. Поэтому, как только вы добавляете nginx, он должен сделать SSL handshake (обмен ключами, аутентификация) и шифрование, которые требуют гораздо больше ресурсов. Затем он разбирает заголовки. Затем он должен создать ещё одно TCP соединение с Varnish.

Опять же, в вышеупомянутой статье Intel, у них 28 ядер, и они сделали некоторую настройку своего OpenSSL, чтобы сделать 38k HTTPS cps (немного больше, чем ваша Varnish производительность). У вас около 1/5 ядра, и на вас влияют ваши виртуальные соседи.

Цитируя Список экземпляров Amazon EC2:

Например, t2.small экземпляр получает кредиты непрерывно на скорость 12 процессорных кредитов в час. Эта возможность обеспечивает базовый уровень производительность, эквивалентная 20% от ядра процессора.

И еще одна статья от самого nginx:

Резюме результатов Одиночное виртуализированное ядро Intel может обычно выполнять до 350 полных 2048-битных операций рукопожатия по протоколу SSL в секунду, используя современные криптографические шифры. Это соответствует нескольким сотням Новые пользователи вашего сервиса в секунду на ядро.

2
ответ дан 3 December 2019 в 20:51

Теги

Похожие вопросы