如何使用 SSL 终止功能优化 HAProxy 到 Ubuntu 上的 Nginx 后端?
设置工作正常,路由正确。但是,当我使用 HAProxy 执行 SSL 终止时,性能会受到很大影响(下面的测试)。密钥是 4096 位 rsa。HAProxy 强制使用 HTTPS 进行验证,然后终止 SSL,并将 HTTP 传达给后端 Nginx 服务器。Nginx 服务器相同,并提供多个静态页面,即 192.168.1.xx/page1.html、192.168.1.xx/page2.html 等。(我包含了 NodeJS 以保证系统的完整性,但只增加了不到 1ms 的延迟。NodeJS 可以忽略。)
以下是设置、配置和当前测试。每个虚拟机 (VM) 都运行 Ubuntu 14.04,并且可以拥有可变数量的 CPU 和 RAM。
- 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
- NodeJS-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
以下是对其中一台 Nginx 服务器进行的 ApacheBench (ab) 测试:
$ 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)
以下是使用 http 对 HAProxy 进行的 ApacheBench (ab) 测试:
$ 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)
以下是使用 https 对 HAProxy 进行的 ApacheBench (ab) 测试:
$ 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)
这是在 HAProxy VM 上进行的 OpenSSL 测试。
$ 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 sign/s、4517.4 verify/s。但是,带有 SSL 终止的 HAProxy 执行速度约为 17 request/s。当然,我们可以获得较小的密钥来提高整体性能,但这并不能解决从 openssl 速度测试到 HAProxy 的速度提高约 4.5 倍的问题(如果存在问题的话)。
那么,根据这些信息,是否存在可以提高性能的最佳 HAProxy 配置?我是否遗漏了某些内容,例如:当用户第一次访问某个页面时,他们只需“签名”一次,并且对该页面的所有并发请求都只需“验证”。如果是这样,那么 AB 测试就无法适当地衡量这一点(如果我错了,请纠正我)。并且,要实现这一点,用户是否必须访问同一个 Nginx 服务器?如果是这样,是否需要保持会话?
为了回答我自己的问题,我尝试从这篇文章中添加粘性会话:带有 SSL 和粘性会话的 HAProxy并使用 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
那么,我只能接受这种性能吗?有些地方提到,4096 位密钥的请求率也类似,约为 75 毫秒/请求。 https://certsimple.com/blog/measuring-ssl-rsa-keys
或者,我的 HAProxy 配置不当,在某处处理 SSL 2x?ServerFault:/questions/574582/nginx-ssl-termination-slow
答案1
需要考虑的一点是,许多 HTTP 客户端(包括浏览器)都试图将 SSL 握手的成本分摊到多个 HTTP 请求中。也就是说,它们与服务器建立一个 TCP 连接,执行 SSL 握手,然后将该 TCP 连接(及其 SSL 会话)重新用于多个请求/响应,而不是每个请求都执行一次 SSL 握手。
为了在您的设置中启用这种场景/测试,您可以在-k
命令行中包含 选项ab
,以便前端HTTP 请求。
另一个考虑因素是您对option http-server-close
HAproxy 设置的使用。这会告诉haproxy
您针对每个前端 HTTP 请求建立一个新的后端 TCP 连接;这可能会增加 40-100 毫秒(甚至更多),具体取决于后端网络。如果您允许 HAproxy 保持这些后端 TCP 连接打开,那么这也可能会减少 报告的每个请求延迟ab
。
根据您预期的 SSL 会话数量,增加 SSL 会话缓存的内存分配(HAproxy 的tune.ssl.cachesize
设置,可能与增加缓存超时结合tune.ssl.lifetime
,从而增加会话缓存重用的可能性)也可能会允许更多恢复的 SSL 会话(以及更快/计算强度更低的 SSL 握手)。
ab
但是我认为,当使用 keep-alive( )时,报告的数字-k
将更好地证明对许多 HTTP 请求重新使用相同的 SSL 会话(通过相同的 TCP 连接)的有效性。
希望这可以帮助!
答案2
进行苹果与苹果之间的比较。
您的基准测试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
)。