Nginx

NGINX HTTPS 反向代理 - 快速 TTFB 但低並發

  • June 24, 2015

我有一個執行的應用程序: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 的核心,並受到虛擬鄰居的影響。

引用Amazon EC2 實例列表

例如,一個 t2.small 實例以每小時 12 個 CPU 積分的速率連續接收積分。此功能提供相當於 CPU 核心 20% 的基準性能。

還有來自 nginx 自己的另一篇論文:

結果總結 單個虛擬化英特爾核心通常每秒可以執行多達 350 次完整的 2048 位 SSL 握手操作,使用現代加密密碼。這相當於每個核心每秒有數百個新使用者使用您的服務。

引用自:https://serverfault.com/questions/700818