2016ArchSummit-https 性能優化

該分享主要兩部分:
1.分析https的性能瓶頸點 2.根據瓶頸點的優化方案

性能分析

https比起http的缺點主要是慢和貴,慢主要體現在未經過任何優化的https比http要慢幾百毫秒,在移動端,甚至有500毫秒以上。貴主要體現在計算性能和服務器成本,服務端需要不斷做加解密操作。https比http多了一層tls協議,因此這些性能問題也主要是tls的問題。關務tls的握手過程和加解密過程,可以參考阮一峰的博客,筆者看過覺得通俗易懂,更能便于理解tls的性能優化點。
1.關于ssl握手過程
http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
2.關于數字簽名
http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html
3.關于RSA原理
http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
po出演講中的兩張圖(圖片來自演講ppt)便于理解:

https握手過程.png
https中的計算環節.png

由上圖中,我們可以看到https中主要有四個計算環節,證書校驗、非對稱密鑰交換、對稱加解密和完整性校驗。證書校驗保證雙方的身份的合法性,非對稱秘鑰交換主要用來生成保密數據的對稱秘鑰,完整性主要保證數據的完整性,不被篡改。

從上圖的握手耗時,我們可以看到在ECDHE_RSA 非對稱密鑰交換握手中,其中ServerKeyExchange過程,耗時2.4毫秒,在演講者的性能試驗中,CPU的一核每秒只能處理400多次。這里補充一下這個過程耗時嚴重的原因,ServerKeyExchange過程其實就是使用DH算法中,服務端使用RSA算法的私鑰對DH參數做數字簽名,這個過程因為使用服務端的私鑰加密,私鑰的位數一般是遠大于公鑰的,因為計算復雜度很高,就會非常耗時。同樣在通用的RSA非對稱秘鑰中,服務端同樣會因為需要使用私鑰去解密客戶端傳來pre-master key,因而同樣會存在耗時嚴重的問題。

對于握手耗時,演講者也給出了其他計算過程的耗時實驗統計。如下圖

其他計算性能.png

上圖統計可以看出性能最好的是AES-128-GCM,性能最差的是AES-256-CBC,但即使它性能最差,它也只需要47微秒就能處理4000個字節,性能相比來說也還能接受。

根據上面的統計可以看出,非對稱密鑰交換過程的耗時占據了整體耗時75%左右,而對稱加密對性能影響較小。

優化方案

簡化握手過程

方式一:使用Session ID。Session ID由服務器生成并返回給客戶端,客戶端再次發起SSL握手時會攜帶上Session ID,服務端拿到后會從自己的內存查找,如果找到便意味著客戶端之前已經發生過完全握手,是可以信任的,然后可以直接進行簡化握手。
缺點:在使用Nginx時,只支持單機多進程間共享的Session Cache。假如接入用的是一臺服務器、一臺Nginx的話,那ID生成和查找都在一起,肯定是可以命中的,但是大部分特別是流量比較大的接入環境都是多臺機器接入,那么當用戶隔了較長時間后攜帶Session ID發起https請求時,可能落到了其他機器上而找不到之前服務器保存的Session ID,導致請求失敗。

方式二:使用分布式Session Cache,服務端會將Session ID寫入全局緩存中,比如redis緩存,這樣用戶下次發起握手時,可以直接從全局的緩存中查找到Session ID,提高成功率。可以參考的開源庫:OpenResty,BoringSSL
缺點:消耗大量緩存。

同時上述兩種方式中,都需要對openssl做改造,因為OpenSSL提供了一個Session Cache的callback可以回調,但是這個回調函數是同步的。這會拖累整體服務性能。BoringSSL中實現了Session Cache的異步查找,可以參考。

方式三:使用Session Ticket,Session Ticket由服務端加密分發給用戶,只要服務端的機器都使用相同的秘鑰,就可以保證簡化握手的成功率。
缺點:服務端需要做解密,影響性能。

Session Ticket,Session ID和Session Cache都有一個共同點,都是基于內存的,但當客戶端重啟,瀏覽器tab關閉后又打開時,會導致Session數據丟失,所以可以采用如下方式:對于安全系數要求不是很高的業務可以控制Session數據存儲在App的私有路徑中,并且有秘鑰開關隨時關閉這個功能。

異步代理耗時計算

雖然簡化握手能提高很多性能,但完全握手在總的握手比例中仍然很高,有30%。所以對完全握手可以把耗時算法分離出來交給計算集群去計算,這個過程是異步的,不需要同步等待計算結果返回。即將耗時圖中ServerKeyExchange過程(設計到私鑰加解密的過程)異步化。

工程實現:Nginx需要改造(這部分沒怎么看懂,后面去了解下Nginx的工作流程)。對OpenSSL改造,需要對OpenSSL的協議棧進行修改,主要涉及到s3_srvr.c這個文件。OpenSSL1.1.0已經支持異步事件。

寫在最后

我司使用的私有協議和tls協議中,tls的性能明顯不如私有協議,目前服務端對tls應該還沒有做優化,可以考慮使用這個分享中異步代理的方式來提高tls的處理性能。畢竟有不少客戶會切到tls協議做請求的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容