提高NodeJS中SSL服務的效能簡單介紹

antzone發表於2017-03-26

在瀏覽網際網路時,通過SSL進行加密是非常重要的。例如在PayPal,安全是首要任務。使用端到端的加密,不僅只公共網站,對於內部服務呼叫也同樣如此。SSL加密技術將在很大程度上影響node.js的效能。已經花時間調整對外的服務,並充分地利用他們。下面是一些發現能顯著地提高SSL對外效能的SSL配置調整清單,下面分別簡單做一下介紹,希望能夠給需要的朋友帶來幫助。

SL密碼:

開箱即用,Node.js 的SSL使用一組非常強大的密碼演算法。特別是,迪菲赫爾曼金鑰交換和橢圓曲線演算法是極其昂貴的。而且當你在預設配置中用了太多的對外SSL呼叫,Node.js的效能將從根本上得到削弱。

為了得到它到底有多慢這個結論,這兒有個服務呼叫的CPU樣本:

[JavaScript] 純文字檢視 複製程式碼
918834.0ms 100.0% 0.0 node (91770)
911376.0ms 99.1% 0.0  start
911376.0ms 99.1% 0.0  node::Start
911363.0ms 99.1% 48.0  uv_run
909839.0ms 99.0% 438.0  uv__io_poll
876570.0ms 95.4% 849.0   uv__stream_io
873590.0ms 95.0% 32.0    node::StreamWrap::OnReadCommon
873373.0ms 95.0% 7.0     node::MakeCallback
873265.0ms 95.0% 15.0     node::MakeDomainCallback
873125.0ms 95.0% 61.0     v8::Function::Call
873049.0ms 95.0% 13364.0    _ZN2v88internalL6InvokeEbNS0
832660.0ms 90.6% 431.0     _ZN2v88internalL21Builtin
821687.0ms 89.4% 39.0      node::crypto::Connection::ClearOut
813884.0ms 88.5% 37.0       ssl23_connect
813562.0ms 88.5% 54.0       ssl3_connect
802651.0ms 87.3% 35.0        ssl3_send_client_key_exchange
417323.0ms 45.4% 7.0         EC_KEY_generate_key
383185.0ms 41.7% 12.0        ecdh_compute_key
1545.0ms 0.1% 4.0          tls1_generate_master_secret
123.0ms 0.0% 4.0           ssl3_do_write
...

重點關注一下金鑰的生成:

[JavaScript] 純文字檢視 複製程式碼
802651.0ms 87.3% 35.0 ssl3_send_client_key_exchange
417323.0ms 45.4% 7.0 EC_KEY_generate_key
383185.0ms 41.7% 12.0 ecdh_compute_key

這個呼叫87%的時間都花在了生成金鑰上!

這些密碼能被改變以減少密集的計算。這個想法已經在https(或代理)得以實現了。例如:

[JavaScript] 純文字檢視 複製程式碼
var agent = new https.Agent({
  "key": key,
  "cert": cert,
  "ciphers": "AES256-GCM-SHA384"
});

金鑰已經沒用昂貴的迪菲赫爾曼金鑰交換。用相似的東西代替之後,下面的樣例能看到顯著的變化:

[JavaScript] 純文字檢視 複製程式碼
...
57945.0ms 32.5% 16.0 ssl3_send_client_key_exchange
28958.0ms 16.2% 9.0 generate_key
26827.0ms 15.0% 2.0 compute_key
...

通過OpenSSL文件,你可以學習更多關於密碼串的東西。

SSL會話恢復:

如果伺服器支援SSL會話恢復,那麼可以通過https(或代理)來傳遞會話。也可以將代理的createConnection函式包裹起來:

[JavaScript] 純文字檢視 複製程式碼
var createConnection = agent.createConnection;
agent.createConnection = function (options) {
  options.session = session;
  return createConnection.call(agent, options);
};

通過給連線增加簡短的握手機制,會話恢復能降低連線數的使用。

保持活動:

允許代理保持活動將緩和SSL握手。一個保持活動的代理,比如agentkeepalive可以修復結點保持活動的問題,但在Node0.12中它是非必須的。

另一個需要銘記的東西是代理的maxSockets,這個值高的話能對效能造成負面的影響。在建立的對外連線數量的基礎上控制maxSockets值。

Slab的大小:

tls.SLAB_BUFFER_SIZE決定了被tls客戶端(伺服器)使用的slab緩衝區的分配大小。它的大小預設為10MB。

這些分配的區間將會擴充套件你的rss且會增加垃圾回收的時間。這意味著高容量將會影響到效能。把這個容量調整到一個比較低的值可以改善記憶體和垃圾收集的效能。在0.12 版本中,slab的分配已經得到改善了,沒有必須再調整了。

SSL在0.12中近期的改變

測試Fedor的SSL增強版。

測試說明

執行一個作為SSL服務代理的http服務,全部執行在本機上。

v0.10.22

[JavaScript] 純文字檢視 複製程式碼
Running 10s test @ <a href="http://127.0.0.1:3000/" target="_blank">http://127.0.0.1:3000/</a>
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 69.38ms 30.43ms 268.56ms 95.24%
Req/Sec 14.95 4.16 20.00 58.65%
3055 requests in 10.01s, 337.12KB read
Requests/sec: 305.28
Transfer/sec: 33.69KB

v0.11.10-pre (從主版本構建)

[JavaScript] 純文字檢視 複製程式碼
Running 10s test @ <a href="http://127.0.0.1:3000/" target="_blank">http://127.0.0.1:3000/</a>
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 75.87ms 7.10ms 102.87ms 71.55%
Req/Sec 12.77 2.43 19.00 64.17%
2620 requests in 10.01s, 276.33KB read
Requests/sec: 261.86
Transfer/sec: 27.62KB

這沒有太多的區別,但這應歸於預設密碼,所以讓我們調整密碼的代理選項。例如:

[JavaScript] 純文字檢視 複製程式碼
var agent = new https.Agent({
  "key": key,
  "cert": cert,
  "ciphers": "AES256-GCM-SHA384"
});

v0.10.22

[JavaScript] 純文字檢視 複製程式碼
Running 10s test @ http://localhost:3000/
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 59.85ms 6.77ms 95.71ms 77.29%
Req/Sec 16.39 2.36 22.00 61.97%
3339 requests in 10.00s, 368.46KB read
Requests/sec: 333.79
Transfer/sec: 36.83KB

v0.11.10-pre (從主版本構建)

[JavaScript] 純文字檢視 複製程式碼
Running 10s test @ http://localhost:3000/
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 38.99ms 5.96ms 71.87ms 86.22%
Req/Sec 25.43 5.70 35.00 63.36%
5160 requests in 10.00s, 569.41KB read
Requests/sec: 515.80
Transfer/sec: 56.92KB

正如所見,經過Fedor的修改,這有著巨大的區別:從0.10到0.12效能差不多差著2倍左右。

相關文章