本次是對一個模塊進行壓測,該模塊對外提供 https 接口,具體功能不用關注,本文主要是介紹整個壓測過程當中發現的性能優化點和優化思路。先會把壓測結果拋出來,本身先思考爲何,因此把分析放在後面。nginx
本次壓測主要是對 CPU 進行壓測,由於在過程當中發現內存的波動和佔用並不大。算法
火焰圖工具:go-torchjson
https抓包工具:ssldump緩存
壓測工具:ab安全
// 服務最高可用內存爲2000Mi,最高可用CPU爲4核
limits:
cpu: "4"
memory: 2000Mi
requests:
cpu: "2"
memory: 1000Mi
複製代碼
在鏈接數量極少的狀況下,性能消耗主要是在json的序列化和反序列化。以下圖:性能優化
(1) 壓測命令 此時的qps爲500bash
ab -n 100000 -c 100 host
複製代碼
(2) 火焰圖 從下圖能夠看出,此時 json 的性能損毀也已經能夠忽略不計,主要是在 https 的徹底握手上了。網絡
通過上面的分析,咱們大體知道了是由於 https 致使的性能損耗,如今我把服務接口改爲 http,再次進行壓測,看看結果如何。session
跟上面的同樣,性能損耗都是在 json 上。分佈式
(1) 壓測命令 此時的qps爲8000
ab -n 100000 -c 100 host
複製代碼
(2) 火焰圖 從下圖能夠看出,此時 json 的性能損毀也已經能夠忽略不計,性能主要消耗在網絡資源獲取,以及一些系統調用:gc,poll等。
在繼續往下看以前,但願你對 https 握手過程已經有了必定的理解。
一次完整的 https 握手,主要的計算點有:
從上面的火焰圖咱們能夠看到,主要的性能消耗是在徹底握手上,即非對稱密鑰交換過程,咱們看看該過程爲何消耗這麼大。 這裏盜了個 ECDHE_RSA 密鑰交換算法性能圖
能夠看到,ServerKeyExchange 用了2.4毫秒的時間, ServerKeyExchange 主要是將接下來要使用的密鑰交換算法的參數進行簽名,因爲 RSA 算法會進行不少次的運算,對 CPU 消耗大。
使用 ssldump 抓包發現協商後的算法套件確實爲:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
優化思路有兩種,一種是減小密鑰交換時間的時間,一種是減小握手的次數。
這個是爲了減小握手的時間,目前這塊咱們線上使用的也是QAT加速卡來加速計算,把計算部分用專門的硬件加速卡來支持,減小CPU的計算量。這塊不展開,詳情可看intel QAT
server 端會在收到 client hello 後生成一個 sessionID 發給 client 並緩存在本地(會加劇 server 的負擔),後續的 SSL 握手,client 在發送 client hello 時候能夠帶上,server 會進行查找,若是命中則說明可信任。可是目前咱們都是多個 nginx,下一次的請求不必定能落到上一次的 nginx 上,因此可以使用分佈式 session cache 來支持。
在徹底握手結束前,server 會給 client 發送一個session ticket,由 client 端進行保存,下次握手時候可帶上,若是 server 可以正確解密,則說明能夠複用。可是這樣在多個 nginx 的場景下,須要多個 nginx 使用相同的私鑰。
其實從http的時候的壓測過程來看,此時gc已經佔到必定的比重了,並且經過監控gc數據可知道,在壓測過程gc每分鐘達到70次,雖然每次gc耗時很短。這主要是由於使用了大量的臨時對象致使的。後續的優化會使用對象池和選擇合適GOGC參數。gc日誌以下圖,有興趣的能夠分析下