這個(gè)分享主要對提升WEB性能延蟹,在協(xié)議層面討論優(yōu)化的方案评矩,主要分三個(gè)層面優(yōu)化,TCP層面阱飘,TLS層斥杜,HTTP層。文中截圖來自分享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è)置
# 打開客戶端TFO
sysctl -w net.ipv4.tcp_fastopen=1
# 打開服務(wù)端TFO
sysctl -w net.ipv4.tcp_fastopen=2
# 同時(shí)打開客戶端和服務(wù)端TFO選項(xiàng)
sysctl -w net.ipv4.tcp_fastopen=3
TFO的基本步驟如下:
- 客戶端發(fā)送一個(gè)SYN包到服務(wù)器蔗喂,這個(gè)包中攜帶了Fast Open Cookie請求的TCP選項(xiàng);
- 服務(wù)器生成一個(gè)cookie高帖,這個(gè)cookie是通過使用密鑰加密客戶端的IP地址生成的缰儿。服務(wù)器給客戶端發(fā)送SYN|ACK響應(yīng),在響應(yīng)包的選項(xiàng)中包含了這個(gè)cookie散址;
- 客戶端存儲這個(gè)cookie以便將來再次與這個(gè)服務(wù)器的IP建立TFO連接時(shí)使用乖阵;
- 再次發(fā)起tcp連接請求,客戶端發(fā)送一個(gè)攜帶應(yīng)用數(shù)據(jù)和以TCP選項(xiàng)方式存儲的Fast Open cookie的SYN包预麸;
-
服務(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蹈矮,接下來走三次握手的普通流程;
tfo01.png
客戶端測試代碼
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ù)器申請一個(gè)TFO cookie,數(shù)據(jù)并不在連接建立過程中送達(dá)踊东;客戶端拿到TFO cookie后北滥,客戶端每次用同樣方式發(fā)送數(shù)據(jù)時(shí)都會在SYN包中攜帶數(shù)據(jù)勺美。
在VM中雙核2g內(nèi)存的CentOS中對比普通建連和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 請求),服務(wù)端在 TLS 握手完成時(shí)直接返回應(yīng)用數(shù)據(jù)(如 HTTP 響應(yīng))遗菠。這樣联喘,應(yīng)用數(shù)據(jù)的發(fā)送實(shí)際上并未等到握手全部完成,故謂之搶跑辙纬。
啟用 False Start 之后豁遭,TLS 階段只需要一次 RTT 就可以開始傳輸應(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**
通過會話復(fù)用闪幽,提高tls連接速度,是 TLS 握手中生成的 Session ID涡匀。服務(wù)端可以將 Session ID 協(xié)商后的信息存起來盯腌,瀏覽器也可以保存 Session ID,并在后續(xù)的 ClientHello 握手中帶上它陨瘩,如果服務(wù)端能找到與之匹配的信息腕够,就可以完成一次快速握手。
Session Ticket
Session Identifier 機(jī)制有一些弊端
- 負(fù)載均衡中舌劳,多機(jī)之間往往沒有同步 Session 信息帚湘,如果客戶端兩次請求沒有落在同一臺機(jī)器上就無法找到匹配的信息
- 服務(wù)端存儲 Session ID 對應(yīng)的信息不好控制失效時(shí)間,太短起不到作用蒿囤,太長又占用服務(wù)端大量資源客们。
Session Ticket可以解決這些問題,Session Ticket 是用只有服務(wù)端知道的安全密鑰加密過的會話信息材诽,最終保存在瀏覽器端底挫。瀏覽器如果在 ClientHello 時(shí)帶上了 Session Ticket,只要服務(wù)器能成功解密就可以完成握手脸侥。
** OCSP Stapling**
證書頒發(fā)者有時(shí)候需要作廢某些證書建邓,證書使用者可以通過 OCSP(Online Certificate Status Protocol,在線證書狀態(tài)協(xié)議)查詢證書是否已經(jīng)作廢睁枕」俦撸客戶端會在 TLS 握手階段進(jìn)一步協(xié)商時(shí)沸手,實(shí)時(shí)查詢 OCSP 接口,并在獲得結(jié)果前阻塞后續(xù)流程注簿,這對性能影響很大契吉。使用OCSP Stapling,可以使服務(wù)端在證書鏈中包含頒發(fā)機(jī)構(gòu)對證書的 OCSP 查詢結(jié)果诡渴,從而讓瀏覽器跳過自己去驗(yàn)證的過程捐晶。服務(wù)端有更快的網(wǎng)絡(luò),獲取 OCSP 響應(yīng)更容易妄辩,也可以將 OCSP 響應(yīng)緩存起來惑灵。從而提高TLS握手的速度。
0-RTT Handshake
在即將發(fā)布的TLS1.3中眼耀,服務(wù)器可以把自己的 ECDH 公鑰長期緩存在客戶端英支,那么客戶端就可以用緩存里的ECDHE公鑰,構(gòu)造一個(gè)電子信封哮伟,在第一個(gè)RTT里干花,直接就發(fā)送應(yīng)用層數(shù)據(jù)了。
HTTP層面
使用http2
HTTP/2 并沒有改動 HTTP/1 的語義部分楞黄,例如請求方法把敢、響應(yīng)狀態(tài)碼、URI 以及頭部字段等核心概念依舊存在谅辣。HTTP/2 最大的變化是重新定義了格式化和傳輸數(shù)據(jù)的方式修赞,這是通過在高層 HTTP API 和低層 TCP 連接之間引入二進(jìn)制分幀層來實(shí)現(xiàn)的。這樣帶來的好處是原來的 WEB 應(yīng)用完全不用修改桑阶,就能享受到協(xié)議升級帶來的收益柏副。
HTTP/2相對于HTTP1的優(yōu)點(diǎn):
- 使用一個(gè)連接,握手少蚣录,頭部做壓縮割择,更好地利用TCP特性;
- 連接復(fù)用萎河,減少域名解析的時(shí)間荔泳;
- HTTP/2 的多路復(fù)用特性,使得可以在一個(gè)連接上同時(shí)打開多個(gè)流虐杯,雙向傳輸數(shù)據(jù)玛歌;
- Server Push,意味著服務(wù)端可以在發(fā)送頁面 HTML 時(shí)主動推送其它資源擎椰,而不用等到瀏覽器解析到相應(yīng)位置支子,發(fā)起請求再響應(yīng)。
寫在最后
針對這個(gè)分享之后达舒,自己的一點(diǎn)思考值朋。發(fā)現(xiàn)這些優(yōu)化策略中有不少共同點(diǎn)叹侄,如復(fù)用,提前傳輸數(shù)據(jù)昨登。在我司的產(chǎn)品中趾代,在tls協(xié)議的使用中,可以嘗試上述的一些優(yōu)化策略丰辣,對TCP重連場景稽坤,也可以嘗試使用TFO機(jī)制,但TFO需要較高的內(nèi)核版本糯俗,在端上未必能支持。