超極速優(yōu)化:網(wǎng)絡(luò)開發(fā)中的請求合并!
今天,xjjdog來分享網(wǎng)絡(luò)開發(fā)中的一個(gè)超級(jí)技巧。它可以把兩個(gè)請求合并為一個(gè)請求,使得服務(wù)在弱網(wǎng)環(huán)境中性能得到極大的改善。
說開了很容易,但卻很難想到。
需求
如果我有大量的物聯(lián)網(wǎng)設(shè)備,比如說100萬臺(tái)。如果這些設(shè)備平均每10秒產(chǎn)生一個(gè)請求,那么QPS就是10W,這對(duì)于任何公司來說都是一個(gè)不小的規(guī)模了。
涉及到交易等有變更的需求,為了實(shí)現(xiàn)冪等操作,通常會(huì)提前申請一個(gè)交易號(hào)(或者說token),來進(jìn)行唯一的交易請求。
這樣,完成一個(gè)交易,需要至少發(fā)起兩個(gè)請求。一個(gè)是申請token,一個(gè)是拿著token做交易。
雖然說生成token很快,但它是從網(wǎng)絡(luò)上傳輸?shù)摹G也徽f現(xiàn)在都是異步模型,就拿網(wǎng)絡(luò)延遲來說,就是一個(gè)大的問題。它可能硬生生的把服務(wù)質(zhì)量給降了下去,增加了不確定性,也增加了編碼的復(fù)雜性。
有什么辦法來加快這個(gè)過程嗎?
從HTTP中學(xué)習(xí)經(jīng)驗(yàn)
大多數(shù)人都知道,TCP有三次握手和四次揮手的機(jī)制。這種冗長的對(duì)話雖然保證了連接的可靠性,但卻損失了不少性能。HTTP從一到三各個(gè)版本,都是在盡量減少HTTP連接的個(gè)數(shù),也在減少交互的次數(shù)。
在比較早的HTTP1.0實(shí)現(xiàn)中,如果需要從服務(wù)端獲取大量資源,會(huì)開啟N條TCP短鏈接,并行的獲取信息。但由于TCP的三次握手和四次揮手機(jī)制,在連接數(shù)量增加的時(shí)候,整體的代價(jià)就變得比較大
在HTTP/1.1中,通過復(fù)用長連接,來改善這個(gè)情況,但問題是,由于TCP的消息確認(rèn)機(jī)制和順序機(jī)制以及流量控制策略的原因,資源獲取必須要排隊(duì)使用。一個(gè)請求,需要等待另外一個(gè)請求傳輸完畢,才能開始
HTTP/2采用多路復(fù)用,多個(gè)資源可以共用一個(gè)連接。但它解決的只是應(yīng)用層的復(fù)用,在TCP的傳輸上依然是阻塞的,后面的資源需要等待前面的傳輸完畢才能繼續(xù)。這就是隊(duì)頭阻塞現(xiàn)象(Head-of-line blocking)
QUIC,也就是HTTP3,抽象出了一個(gè)stream(流)的概念,多個(gè)流,可以復(fù)用一條連接,那么滑動(dòng)窗口這些概念就不用作用在連接上了,而是作用在stream上。由于UDP只管發(fā)送不管成功與否的特性,這些數(shù)據(jù)包的傳輸就能夠并發(fā)執(zhí)行。協(xié)議的server端,會(huì)解析并緩存這些數(shù)據(jù)包,進(jìn)行組裝和整理等。由于抽象出了stream的概念,就使得某個(gè)數(shù)據(jù)包傳輸失敗,只會(huì)影響單個(gè)stream的準(zhǔn)確性,而不是整個(gè)連接的準(zhǔn)確性。
請求黏貼
其實(shí),我們參考TCP的三次握手就可以了。TCP的握手和揮手流程都差不多,但為什么握手是三次,但揮手是四次呢?
原因就是TCP把SYN和ACK兩個(gè)報(bào)文,合并成一個(gè)返回了。
我們可以把token看作是序列號(hào),然后把它黏貼在正常的請求里返回就可以了。
比如,原來的請求是。
一、獲取token
request: /getToken
response:
{
"token": "12345"
}
二、提交請求
request: /postOrder
{
"token": "12345",
"other": {}
}
response:
{
"status": 200
}
合并后的請求是。
request: /postOrder
{
"token": "12345",
"other": {}
}
response:
{
"status": 200,
"token": "12346"
}
只需要在每次請求返回的時(shí)候,不論成功還是失敗,都附加一個(gè)新的token到客戶端。客戶端緩存這個(gè)token,然后發(fā)起下個(gè)請求。
通過這個(gè)方法,就可以把兩個(gè)請求合并為1個(gè)請求,完成我們的優(yōu)化目標(biāo)。
End
在網(wǎng)絡(luò)編程中,減少網(wǎng)絡(luò)交互是一個(gè)非常重要的優(yōu)化,尤其是在弱網(wǎng)環(huán)境中。雖然這個(gè)技巧很簡單,但它很難被想到。優(yōu)化效果也是巨大的,畢竟減少了一次網(wǎng)絡(luò)交互。
它有一個(gè)響亮的名字,那就是三連環(huán)。意味著前后請求的銜接,永不斷環(huán)。
作者簡介:小姐姐味道 (xjjdog),一個(gè)不允許程序員走彎路的公眾號(hào)。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。