從一次效能優化看https的效能

奇犽發表於2019-03-24

一,背景介紹

本次是對一個模組進行壓測,該模組對外提供 https 介面,具體功能不用關注,本文主要是介紹整個壓測過程中發現的效能優化點和優化思路。先會把壓測結果丟擲來,自己先思考為什麼,所以把分析放在後面。

二,壓測和分析

本次壓測主要是對 CPU 進行壓測,因為在過程中發現記憶體的波動和佔用並不大。

2.1 資訊告知

2.1.1 工具

火焰圖工具:go-torch

https抓包工具:ssldump

壓測工具:ab

2.1.2 服務資源配置

// 服務最高可用記憶體為2000Mi,最高可用CPU為4核
limits:
  cpu: "4"
  memory: 2000Mi
requests:
  cpu: "2"
  memory: 1000Mi
複製程式碼

2.2 https時候的壓測

2.2.1 壓測前

在連線數量極少的情況下,效能消耗主要是在json的序列化和反序列化。如下圖:

從一次效能優化看https的效能

2.2.2 壓測

(1) 壓測命令 此時的qps為500

ab -n 100000 -c 100  host
複製程式碼

(2) 火焰圖 從下圖可以看出,此時 json 的效能損毀也已經可以忽略不計,主要是在 https 的完全握手上了。

從一次效能優化看https的效能

2.2.4 問題

  • 1,為什麼 https 的握手效能消耗這麼嚴重

2.3 http時候的壓測

經過上面的分析,我們大致知道了是因為 https 導致的效能損耗,現在我把服務介面改成 http,再次進行壓測,看看結果如何。

2.3.1 壓測前

跟上面的一樣,效能損耗都是在 json 上。

2.3.2 壓測鏈路:直接訪問鏈路

(1) 壓測命令 此時的qps為8000

ab -n 100000 -c 100 host
複製程式碼

(2) 火焰圖 從下圖可以看出,此時 json 的效能損毀也已經可以忽略不計,效能主要消耗在網路資源獲取,以及一些系統呼叫:gc,poll等。

從一次效能優化看https的效能

三,效能分析

在繼續往下看之前,希望你對 https 握手過程已經有了一定的理解。

3.1 https的效能損耗為什麼這麼嚴重

3.1.1 原因分析

一次完整的 https 握手,主要的計算點有:

  • 非對稱金鑰交換:使用 RSA, Diffie-Hellman, ECDHE等演算法,經過高強度金鑰生成演算法,生成對稱金鑰
  • 對稱加密解密:使用上面生成的對稱金鑰,對訊息進行加密解密
  • 訊息一致性驗證:每一段加密的內容都會附加一個 MAC 訊息,即訊息認證碼。簡單地說就是對內容進行的安全雜湊計算,接收方需要校驗 MAC 碼。
  • 證書籤名驗證:客戶端驗證服務端證書

從上面的火焰圖我們可以看到,主要的效能消耗是在完全握手上,即非對稱金鑰交換過程,我們看看該過程為什麼消耗這麼大。 這裡盜了個 ECDHE_RSA 金鑰交換演算法效能圖

從一次效能優化看https的效能

可以看到,ServerKeyExchange 用了2.4毫秒的時間, ServerKeyExchange 主要是將接下來要使用的金鑰交換演算法的引數進行簽名,由於 RSA 演算法會進行很多次的運算,對 CPU 消耗大。

使用 ssldump 抓包發現協商後的演算法套件確實為:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

3.1.2 優化思路

優化思路有兩種,一種是減少金鑰交換時間的時間,一種是減少握手的次數。

(1) 平行計算

這個是為了減少握手的時間,目前這塊我們線上使用的也是QAT加速卡來加速計算,把計算部分用專門的硬體加速卡來支援,減少CPU的計算量。這塊不展開,詳情可看intel QAT

(2) 使用sessionID

server 端會在收到 client hello 後生成一個 sessionID 發給 client 並快取在本地(會加重 server 的負擔),後續的 SSL 握手,client 在傳送 client hello 時候可以帶上,server 會進行查詢,如果命中則說明可信任。但是目前我們都是多個 nginx,下一次的請求不一定能落到上一次的 nginx 上,所以可使用分散式 session cache 來支援。

(3) 使用sessionTicket

在完全握手結束前,server 會給 client 傳送一個session ticket,由 client 端進行儲存,下次握手時候可帶上,如果 server 能夠正確解密,則說明可以複用。但是這樣在多個 nginx 的場景下,需要多個 nginx 使用相同的私鑰。

四,其他優化點

4.1 gc

其實從http的時候的壓測過程來看,此時gc已經佔到一定的比重了,而且通過監控gc資料可知道,在壓測過程gc每分鐘達到70次,雖然每次gc耗時很短。這主要是因為使用了大量的臨時物件導致的。後續的優化會使用物件池和選擇合適GOGC引數。gc日誌如下圖,有興趣的可以分析下

從一次效能優化看https的效能

相關文章