Оптимизация SSL-терминации HAProxy (с бэкэндом Nginx в Ubuntu)
Как я могу оптимизировать HAProxy с SSL-терминацией для бэкэндов Nginx в Ubuntu?
Настройка работает нормально и маршруты правильно. Однако, когда я выполняю SSL-завершение с помощью HAProxy, это приводит к огромному снижению производительности (тесты приведены ниже). Ключ 4096-битный RSA. HAProxy заставляет HTTPS для проверки, затем прекращает работу SSL и передает HTTP для внутренних серверов Nginx. Серверы Nginx идентичны и обслуживают несколько статических страниц, например, 192.168.1.xx/page1.html, 192.168.1.xx/page2.html и т. Д. (Я включил NodeJS для полноты своей системы, но добавляю задержку только <1 мс. NodeJS можно игнорировать.)
Вот настройки, конфиги и текущие тесты. Каждая виртуальная машина (ВМ) работает под управлением Ubuntu 14.04 и может иметь различное количество процессоров и оперативной памяти.
- HAProxy (1.5.14): 192.168.1.10
- Nginx-1: 192.168.1.20
- Nginx-2: 192.168.1.21
- Nginx-3: 192.168.1.22
- Узел JS-1: 192.168.1.30
Вот конфигурация HAProxy:
global
maxconn 40000
tune.ssl.default-dh-param 2048
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/harding-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
option forwardfor
option http-server-close
stats enable
stats uri /stats
stats realm Haproxy\ Statistics
stats auth user:password
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend www-http
bind 192.168.1.10:80
reqadd X-Forwarded-Proto:\ http
default_backend www-backend
frontend www-https
bind 192.168.1.10:443 ssl crt /etc/ssl/private/company.pem
reqadd X-Forwarded-Proto:\ https
use_backend node-backend if { path_beg /socket.io }
default_backend www-backend
backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 192.168.1.20:80 check
server www-2 192.168.1.21:80 check
server www-3 192.168.1.22:80 check
backend node-backend
server node-1 192.168.1.30:8888 check
Вот тест ApacheBench (ab) для одного из серверов Nginx:
$ ab -c 200 -n 10000 http://192.168.1.20/
Server Software: nginx/1.4.6
Server Hostname: 192.168.1.20
Server Port: 80
Document Path: /
Document Length: 3130 bytes
Concurrency Level: 200
Time taken for tests: 2.257 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 33720000 bytes
HTML transferred: 31300000 bytes
Requests per second: 4430.21 [#/sec] (mean)
Time per request: 45.145 [ms] (mean)
Time per request: 0.226 [ms] (mean, across all concurrent requests)
Transfer rate: 14588.55 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 4 27 104.3 16 1187
Processing: 4 18 8.2 16 358
Waiting: 3 18 7.9 16 334
Total: 9 45 105.8 32 1225
Percentage of the requests served within a certain time (ms)
50% 32
66% 41
75% 43
80% 44
90% 49
95% 52
98% 55
99% 57
100% 1225 (longest request)
Вот тест ApacheBench (ab) для HAProxy с http:
$ ab -c 200 -n 10000 http://192.168.1.10/
Server Software: nginx/1.4.6
Server Hostname: 192.168.1.10
Server Port: 80
Document Path: /
Document Length: 3130 bytes
Concurrency Level: 200
Time taken for tests: 1.918 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 33720000 bytes
HTML transferred: 31300000 bytes
Requests per second: 5215.09 [#/sec] (mean)
Time per request: 38.350 [ms] (mean)
Time per request: 0.192 [ms] (mean, across all concurrent requests)
Transfer rate: 17173.14 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 3 18 3.5 18 32
Processing: 7 20 3.5 19 36
Waiting: 7 20 3.4 19 36
Total: 15 38 4.2 37 57
Percentage of the requests served within a certain time (ms)
50% 37
66% 38
75% 39
80% 40
90% 44
95% 46
98% 50
99% 51
100% 57 (longest request)
Вот тест ApacheBench (ab) для HAProxy с https:
$ ab -c 200 -n 10000 https://192.168.1.10/
Server Software: nginx/1.4.6
Server Hostname: 192.168.1.10
Server Port: 443
SSL/TLS Protocol: TLSv1,DHE-RSA-AES256-SHA,2048,256
Document Path: /
Document Length: 3130 bytes
Concurrency Level: 200
Time taken for tests: 566.303 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 33720000 bytes
HTML transferred: 31300000 bytes
Requests per second: 17.66 [#/sec] (mean)
Time per request: 11326.069 [ms] (mean)
Time per request: 56.630 [ms] (mean, across all concurrent requests)
Transfer rate: 58.15 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 483 8982 3326.6 11090 14031
Processing: 16 2255 3313.0 43 11399
Waiting: 14 2186 3253.3 35 11252
Total: 5648 11237 879.1 11212 22732
Percentage of the requests served within a certain time (ms)
50% 11212
66% 11274
75% 11308
80% 11321
90% 11395
95% 11641
98% 11847
99% 14063
100% 22732 (longest request)
Вот тест OpenSSL на виртуальной машине HAProxy.
$ openssl speed rsa
sign verify sign/s verify/s
rsa 512 bits 0.000081s 0.000006s 12314.6 179042.8
rsa 1024 bits 0.000277s 0.000017s 3603.7 60563.8
rsa 2048 bits 0.001852s 0.000058s 539.8 17231.3
rsa 4096 bits 0.013793s 0.000221s 72.5 4517.4
Таким образом, с моей точки зрения HAProxy не может превзойти тест скорости openssl 72,5 знака / с, 4517,4 проверки / с. Однако HAProxy с завершением SSL выполняет около 17 запросов / с. Конечно, мы можем получить меньший ключ для повышения общей производительности, но это не решает проблему (если проблема существует) увеличения скорости ~4.5x от теста скорости openssl до HAProxy.
Итак, учитывая эту информацию, существует ли оптимальная конфигурация HAProxy, которая увеличит производительность? Например, я что-то упускаю: когда пользователь заходит на страницу в первый раз, ему нужно только "подписать" один раз, а все одновременные запросы к странице только "подтвердить". Если это так, то тест АБ не измеряет это должным образом (поправьте меня, если я ошибаюсь). И чтобы это произошло, должен ли пользователь посещать один и тот же сервер Nginx? Если так, это требует сессий палки?
Пытаясь ответить на мои собственные вопросы, я попытался добавить липкие сессии из этого поста: HAProxy с SSL и липкими сессиями и использовал Siege для тестирования с несколькими URL-адресами. Тем не менее, по-прежнему не было повышения производительности.
$ siege -c 100 -r 10 -b -f urls.txt
Transactions: 1000 hits
Availability: 100.00 %
Elapsed time: 22.56 secs
Data transferred: 2.84 MB
Response time: 2.17 secs
Transaction rate: 44.33 trans/sec
Throughput: 0.13 MB/sec
Concurrency: 96.06
Successful transactions: 1000
Failed transactions: 0
Longest transaction: 8.96
Shortest transaction: 0.16
Где urls.txt
URL=https://192.168.1.10/
$(URL)
$(URL)page1.html
$(URL)page2.html
Итак, я застрял в этом спектакле? В некоторых местах упоминается аналогичная частота запросов ~75 мс / запрос для 4096-битных ключей. https://certsimple.com/blog/measuring-ssl-rsa-keys
Или мой HAProxy плохо настроен и где-то обрабатывает SSL 2x? ServerFault: /questions/574582/nginx-ssl-termination-slow
2 ответа
Следует учитывать, что многие клиенты HTTP (включая браузеры) пытаются амортизировать стоимость рукопожатия SSL по нескольким запросам HTTP. То есть они устанавливают одно TCP-соединение с сервером, выполняют SSL-квитирование, а затем повторно используют это TCP-соединение (с его сеансом SSL) для нескольких запросов / ответов, вместо того чтобы выполнять SSL-квитирование для каждого запроса.
Чтобы включить этот тип сценария / теста в настройках, вы можете включить -k
опция командной строки для ab
, для вашего веб-интерфейса HTTP-запросов.
Еще одним соображением является использование вами option http-server-close
Настройка HAproxy. Это говорит haproxy
создать новое внутреннее TCP-соединение для каждого HTTP-запроса; это может добавить свои собственные 40-100 мс (если не больше), в зависимости от внутренней сети. Если вы позволили HAproxy сохранять эти внутренние TCP-соединения открытыми, это также может уменьшить задержку для каждого запроса, о которой сообщает ab
,
В зависимости от количества ожидаемых сеансов SSL также возможно, что увеличение объема памяти для кэширования сеансов SSL (HAproxy's tune.ssl.cachesize
настройка, возможно, в сочетании с tune.ssl.lifetime
увеличение времени ожидания кеша и, следовательно, повышение вероятности повторного использования кеша сеанса) позволило бы проводить более возобновленные сеансы SSL (и быстрее / менее требовательные к использованию рукопожатия SSL).
Но я думаю, что цифры, сообщенные ab
, при использовании keep-alive (-k
), лучше продемонстрирует эффективность повторного использования одного и того же сеанса SSL (через одно и то же соединение TCP) для многих HTTP-запросов.
Надеюсь это поможет!
Сравните яблоки с яблоками.
Ваш эталон openssl speed rsa
вероятно, не измеряет время DHE, потому что он не использует эфемерные ключи. Это означает, что вы тестируете менее безопасный алгоритм по сравнению с алгоритмом DHE. Последний медленнее, с другой стороны, он обеспечивает идеальную секретность вперед (PFS).
Но DHE довольно старый, неэффективный, и современные браузеры обычно используют лучшие ECDHE (или даже ECDSA).
Я думаю, что вы должны настроить свой ab тест для обеспечения ECDHE-RSA-AES128-SHA256. Я думаю, вы должны запрограммировать свой тест openssl, чтобы использовать цикл openssl s_client -cipher ECDHE-RSA-AES128-SHA256
(вместо упрощенного openssl speed
).