NGINX HTTPS 反向代理 - 快速 TTFB 但低並發
我有一個執行的應用程序:NGINX (SSL) => VARNISH (CACHE) => APACHE/PHP。
執行ab benchmark,我能夠通過 EC2 t2.small 實例在清漆層(通過 HTTP)上實現 30k+ 請求/秒。但是,當我通過 NGINX (HTTPS) 執行測試時,我只能推送 160 個請求/秒(來自公共網路的 TTFB 平均為 43 毫秒)。
@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;
@域.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
這是 Varnish 的基準(它之前以 20-30k 執行 - 用完了我的 CPU 週期,平均 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
這是通過HTTP進行 NGINX 的基準測試
內部 => @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
這是通過HTTPS的 NGINX 基準測試
內部 => @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
好吧,從您提供(和未提供)的資訊來看,我只能猜測。但是從實例類型(t2 具有基於票證的突發性能,當票證用完時,獲得大約 20% 的核心;這不是一個做基準測試的好實例)和
ab
用於測試的用途(順便說一句。當你寫它時作為“AB 測試”,首先想到的是這個)我會說你的表現幾乎符合預期。啟動 SSL 或 TLS 會話時,性能最密集的任務不是數據加密/解密,而是密鑰交換。由於
ab
不使用 SSL 會話記憶體,因此必須在每個連接上進行密鑰交換。根據實際使用的 cipher/kex/auth 套件(不知道,沒有
ab
提供輸出),這對 CPU 來說可能是相當多的工作。而且由於兩端都在同一台機器上,因此每個連接的 CPU 需求增加了一倍(這是一種簡化,但在這裡已經足夠好了)。在實際使用中,keep alives 可能會幫助您獲得更好的性能(取決於客戶端,普通瀏覽器使用它;嘗試
ab -k
)。而且您將從您提到的 SSL 會話記憶體中獲得更好的性能(再次取決於客戶端,普通瀏覽器支持它)。還有其他幾種方法可以幫助您提高績效。當然,您可以獲得更好的硬體。您可以優化您的密鑰大小(取決於應用程序所需的保護級別) - 較小的密鑰通常更便宜。從不同的機器進行測試可能會或可能不會提高表觀性能。並且獲得不同的 OpenSSL 建構或完全不同的 SSL 庫,也可以提供更好的性能。
僅供參考,您可以查看 Intel 的這篇論文。他們確實比較了高度優化的機器(和一些優化的軟體)上的性能。考慮到您的可用計算能力不到他們的 1/30(如果您沒有票,可能會低至 1/150)。
不過,如果您需要高性能 SSL,可能值得考慮使用 Amazon ELB 為您完成 SSL 終止,因為您已經在 EC2 上。
編輯:例如Apache JMeter使用 ssl 上下文記憶體。httperf也是如此。我發現 JMeter 尤其擅長模擬現實生活中的負載。但是對於這種 httperf 會話記憶體方式可能效果最好。
沒有看到任何差異
-k
可能是因為它仍未使用。取決於並發設置,並且(至少在我的機器上)它似乎也取決於 url。如果我使用指向 url 中多個 IP 的域名(不要問我為什麼),它不會使用 keepalives。根據您對大規模的看法,但我不希望在這個相當小的實例上每秒獲得超過 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 正在做的事情)是盡可能容易的。您解析標題,在記憶體中找到內容,然後將其吐出。Varnish 擅長於此。
建立加密連接是一個完全不同的層次。因此,一旦添加了 nginx,它就必須進行 SSL 握手(密鑰交換、身份驗證)和加密,這需要更多資源。然後它解析標題。然後它必須創建另一個到 Varnish 的 TCP 連接。
同樣,在上述英特爾論文中,他們有 28 個核心,並對他們的 OpenSSL 進行了一些調整,以實現 38k HTTPS cps(比您的 Varnish 性能略高一點)。您擁有大約 1/5 的核心,並受到虛擬鄰居的影響。
例如,一個 t2.small 實例以每小時 12 個 CPU 積分的速率連續接收積分。此功能提供相當於 CPU 核心 20% 的基準性能。
還有來自 nginx 自己的另一篇論文:
結果總結 單個虛擬化英特爾核心通常每秒可以執行多達 350 次完整的 2048 位 SSL 握手操作,使用現代加密密碼。這相當於每個核心每秒有數百個新使用者使用您的服務。