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

一,背景介紹

本次是對一個模塊進行壓測,該模塊對外提供 https 接口,具體功能不用關注,本文主要是介紹整個壓測過程當中發現的性能優化點和優化思路。先會把壓測結果拋出來,本身先思考爲何,因此把分析放在後面。nginx

二,壓測和分析

本次壓測主要是對 CPU 進行壓測,由於在過程當中發現內存的波動和佔用並不大。算法

2.1 信息告知

2.1.1 工具

火焰圖工具:go-torchjson

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的序列化和反序列化。以下圖:性能優化

2.2.2 壓測

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

ab -n 100000 -c 100  host
複製代碼

(2) 火焰圖 從下圖能夠看出,此時 json 的性能損毀也已經能夠忽略不計,主要是在 https 的徹底握手上了。網絡

2.2.4 問題

  • 1,爲何 https 的握手性能消耗這麼嚴重

2.3 http時候的壓測

通過上面的分析,咱們大體知道了是由於 https 致使的性能損耗,如今我把服務接口改爲 http,再次進行壓測,看看結果如何。session

2.3.1 壓測前

跟上面的同樣,性能損耗都是在 json 上。分佈式

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

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

ab -n 100000 -c 100 host
複製代碼

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

三,性能分析

在繼續往下看以前,但願你對 https 握手過程已經有了必定的理解。

3.1 https的性能損耗爲何這麼嚴重

3.1.1 緣由分析

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

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

從上面的火焰圖咱們能夠看到,主要的性能消耗是在徹底握手上,即非對稱密鑰交換過程,咱們看看該過程爲何消耗這麼大。 這裏盜了個 ECDHE_RSA 密鑰交換算法性能圖

能夠看到,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日誌以下圖,有興趣的能夠分析下

相關文章
相關標籤/搜索