2017ArchSummit-WEB加速,協(xié)議先行

這個(gè)分享主要對(duì)提升WEB性能,在協(xié)議層面討論優(yōu)化的方案,主要分三個(gè)層面優(yōu)化,TCP層面,TLS層,HTTP層。文中截圖來(lái)自分享ppt http://ppt.geekbang.org/slide/show/946


TCP層面的優(yōu)化

使用TFO(tcp fast open),使用TFO需要linux 內(nèi)核版本在3.7以上。
內(nèi)核選項(xiàng)設(shè)置

# 打開(kāi)客戶端TFO
sysctl -w net.ipv4.tcp_fastopen=1
# 打開(kāi)服務(wù)端TFO
sysctl -w net.ipv4.tcp_fastopen=2
# 同時(shí)打開(kāi)客戶端和服務(wù)端TFO選項(xiàng)
sysctl -w net.ipv4.tcp_fastopen=3

TFO的基本步驟如下:

  1. 客戶端發(fā)送一個(gè)SYN包到服務(wù)器,這個(gè)包中攜帶了Fast Open Cookie請(qǐng)求的TCP選項(xiàng);
  2. 服務(wù)器生成一個(gè)cookie,這個(gè)cookie是通過(guò)使用密鑰加密客戶端的IP地址生成的。服務(wù)器給客戶端發(fā)送SYN|ACK響應(yīng),在響應(yīng)包的選項(xiàng)中包含了這個(gè)cookie;
  3. 客戶端存儲(chǔ)這個(gè)cookie以便將來(lái)再次與這個(gè)服務(wù)器的IP建立TFO連接時(shí)使用;
  4. 再次發(fā)起tcp連接請(qǐng)求,客戶端發(fā)送一個(gè)攜帶應(yīng)用數(shù)據(jù)和以TCP選項(xiàng)方式存儲(chǔ)的Fast Open cookie的SYN包;
  5. 服務(wù)器驗(yàn)證這個(gè)cookie,如果合法,服務(wù)器發(fā)送一個(gè)SYN|ACK確認(rèn)SYN和數(shù)據(jù),然后數(shù)據(jù)被傳遞到應(yīng)用進(jìn)程;如果不合法,服務(wù)器丟棄數(shù)據(jù),發(fā)送一個(gè)SYN|ACK只確認(rèn)SYN,接下來(lái)走三次握手的普通流程;


    tfo01.png

客戶端測(cè)試代碼

int sockfd, n;  
char recvbuffer[1024], sendbuffer[1024];  
struct sockaddr_in servaddr;  
char buf[20] = {"hello server"};  
int ret = 0;  
  
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
    printf ("create socket error: %s(errno: %d)\n", strerror (errno),  
            errno);  
    exit (0);  
}  
  
memset (&servaddr, 0, sizeof (servaddr));  
servaddr.sin_family = AF_INET;  
servaddr.sin_port = htons (5999);  
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  
ret = sendto(sockfd, buf, strlen(buf), MSG_FASTOPEN,  
        (struct sockaddr *)&servaddr, sizeof(servaddr));  
if (ret < 0) {  
    printf ("send msg error: %s(errno: %d)\n", strerror (errno), errno);  
}  
  
close (sockfd);  

在代碼不需要使用connect,直接sendto發(fā)送數(shù)據(jù)。第一次交互時(shí)只是向服務(wù)器申請(qǐng)一個(gè)TFO cookie,數(shù)據(jù)并不在連接建立過(guò)程中送達(dá);客戶端拿到TFO cookie后,客戶端每次用同樣方式發(fā)送數(shù)據(jù)時(shí)都會(huì)在SYN包中攜帶數(shù)據(jù)。
在VM中雙核2g內(nèi)存的CentOS中對(duì)比普通建連和TFO建連1024次耗時(shí)

普通建連 TFO建連
457ms 285ms

服務(wù)端關(guān)鍵代碼

// 將listenfd設(shè)置TCP_FASTOPEN選項(xiàng)
ret = setsockopt(listenfd, 6, TCP_FASTOPEN, &qlen, sizeof(qlen));

TFO在收到SYN的時(shí)候就創(chuàng)建socket并將數(shù)據(jù)提交給應(yīng)用進(jìn)程,在握手中傳遞數(shù)據(jù)。比普通模式節(jié)省了SYN|ACK與ACK的交互時(shí)間,減小了通信延遲。

TLS層面的優(yōu)化

fasle start
False Start 有搶跑的意思。TLS False Start 是指客戶端在發(fā)送 Change Cipher Spec Finished 同時(shí)發(fā)送應(yīng)用數(shù)據(jù)(如 HTTP 請(qǐng)求),服務(wù)端在 TLS 握手完成時(shí)直接返回應(yīng)用數(shù)據(jù)(如 HTTP 響應(yīng))。這樣,應(yīng)用數(shù)據(jù)的發(fā)送實(shí)際上并未等到握手全部完成,故謂之搶跑。

false start.png

啟用 False Start 之后,TLS 階段只需要一次 RTT 就可以開(kāi)始傳輸應(yīng)用數(shù)據(jù)。使用false start有個(gè)前提是,必須使用支持前向安全性(Forward Secrecy)的加密算法,例如ECDHE。False Start 在尚未完成握手時(shí)就發(fā)送了應(yīng)用數(shù)據(jù),F(xiàn)orward Secrecy 可以提高安全性
** Session Resumption**
通過(guò)會(huì)話復(fù)用,提高tls連接速度,是 TLS 握手中生成的 Session ID。服務(wù)端可以將 Session ID 協(xié)商后的信息存起來(lái),瀏覽器也可以保存 Session ID,并在后續(xù)的 ClientHello 握手中帶上它,如果服務(wù)端能找到與之匹配的信息,就可以完成一次快速握手。

tls_sessionid.png

Session Ticket
Session Identifier 機(jī)制有一些弊端

  1. 負(fù)載均衡中,多機(jī)之間往往沒(méi)有同步 Session 信息,如果客戶端兩次請(qǐng)求沒(méi)有落在同一臺(tái)機(jī)器上就無(wú)法找到匹配的信息
  2. 服務(wù)端存儲(chǔ) Session ID 對(duì)應(yīng)的信息不好控制失效時(shí)間,太短起不到作用,太長(zhǎng)又占用服務(wù)端大量資源。

Session Ticket可以解決這些問(wèn)題,Session Ticket 是用只有服務(wù)端知道的安全密鑰加密過(guò)的會(huì)話信息,最終保存在瀏覽器端。瀏覽器如果在 ClientHello 時(shí)帶上了 Session Ticket,只要服務(wù)器能成功解密就可以完成握手。

tls_ticket.png

** OCSP Stapling**
證書(shū)頒發(fā)者有時(shí)候需要作廢某些證書(shū),證書(shū)使用者可以通過(guò) OCSP(Online Certificate Status Protocol,在線證書(shū)狀態(tài)協(xié)議)查詢證書(shū)是否已經(jīng)作廢??蛻舳藭?huì)在 TLS 握手階段進(jìn)一步協(xié)商時(shí),實(shí)時(shí)查詢 OCSP 接口,并在獲得結(jié)果前阻塞后續(xù)流程,這對(duì)性能影響很大。使用OCSP Stapling,可以使服務(wù)端在證書(shū)鏈中包含頒發(fā)機(jī)構(gòu)對(duì)證書(shū)的 OCSP 查詢結(jié)果,從而讓瀏覽器跳過(guò)自己去驗(yàn)證的過(guò)程。服務(wù)端有更快的網(wǎng)絡(luò),獲取 OCSP 響應(yīng)更容易,也可以將 OCSP 響應(yīng)緩存起來(lái)。從而提高TLS握手的速度。

tls_ocsp stapling.png

0-RTT Handshake
在即將發(fā)布的TLS1.3中,服務(wù)器可以把自己的 ECDH 公鑰長(zhǎng)期緩存在客戶端,那么客戶端就可以用緩存里的ECDHE公鑰,構(gòu)造一個(gè)電子信封,在第一個(gè)RTT里,直接就發(fā)送應(yīng)用層數(shù)據(jù)了。

0RTT.png

HTTP層面

使用http2
HTTP/2 并沒(méi)有改動(dòng) HTTP/1 的語(yǔ)義部分,例如請(qǐng)求方法、響應(yīng)狀態(tài)碼、URI 以及頭部字段等核心概念依舊存在。HTTP/2 最大的變化是重新定義了格式化和傳輸數(shù)據(jù)的方式,這是通過(guò)在高層 HTTP API 和低層 TCP 連接之間引入二進(jìn)制分幀層來(lái)實(shí)現(xiàn)的。這樣帶來(lái)的好處是原來(lái)的 WEB 應(yīng)用完全不用修改,就能享受到協(xié)議升級(jí)帶來(lái)的收益。
HTTP/2相對(duì)于HTTP1的優(yōu)點(diǎn):

  1. 使用一個(gè)連接,握手少,頭部做壓縮,更好地利用TCP特性;
  2. 連接復(fù)用,減少域名解析的時(shí)間;
  3. HTTP/2 的多路復(fù)用特性,使得可以在一個(gè)連接上同時(shí)打開(kāi)多個(gè)流,雙向傳輸數(shù)據(jù);
  4. Server Push,意味著服務(wù)端可以在發(fā)送頁(yè)面 HTML 時(shí)主動(dòng)推送其它資源,而不用等到瀏覽器解析到相應(yīng)位置,發(fā)起請(qǐng)求再響應(yīng)。

寫(xiě)在最后

針對(duì)這個(gè)分享之后,自己的一點(diǎn)思考。發(fā)現(xiàn)這些優(yōu)化策略中有不少共同點(diǎn),如復(fù)用,提前傳輸數(shù)據(jù)。在我司的產(chǎn)品中,在tls協(xié)議的使用中,可以嘗試上述的一些優(yōu)化策略,對(duì)TCP重連場(chǎng)景,也可以嘗試使用TFO機(jī)制,但TFO需要較高的內(nèi)核版本,在端上未必能支持。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容