網(wǎng)頁端用HTTP收消息,怎么做到像TCP一樣100%實(shí)時?

任何脫離業(yè)務(wù)的架構(gòu)設(shè)計都是耍流氓。網(wǎng)頁端收消息,究竟是推還是拉?

需求緣起

對于在網(wǎng)頁端登錄的用戶A,發(fā)送方,也就是消息的來源有幾方面:

系統(tǒng)發(fā)給A的“系統(tǒng)通知”,可能對實(shí)時性要求沒這么高

用戶發(fā)給A的“聊天消息”,有對實(shí)時性要求比較高,越實(shí)時越好

消息的處理方,也就是系統(tǒng)側(cè),一般來說:

有服務(wù)對消息進(jìn)行邏輯處理

有數(shù)據(jù)庫對數(shù)據(jù)進(jìn)行落地

有緩存對數(shù)據(jù)進(jìn)行加速

拋開這些技術(shù)細(xì)節(jié)不談,暫且認(rèn)為服務(wù)端對每一個用戶都有一個“待收消息”的隊列,里面存放了需要給這個用戶的一切消息。

消息的接收方,也就是用戶A,如果是在網(wǎng)頁端登錄,因?yàn)镠TTP協(xié)議是“請求-響應(yīng)”式的,服務(wù)端與網(wǎng)頁之間沒有消息通道,對于這類“收消息”的需求,是如何處理的呢?

方案一、輪詢拉取

輪詢拉取,是最容易想到的實(shí)現(xiàn)方式:

發(fā)送方發(fā)送了消息,先入隊列

網(wǎng)頁端起一個timer,每個一段時間(例如10秒),發(fā)起一個輪詢請求,拉取隊列里的消息

如果隊列里有消息,就返回消息

如果隊列里無消息,就10秒后再次輪詢

這種方式的優(yōu)勢是:實(shí)現(xiàn)簡單,直觀且,容易理解,互聯(lián)網(wǎng)興起時,人數(shù)不多的聊天室就是這么玩的。

畫外音:創(chuàng)辦于1996年的互聯(lián)網(wǎng)老站碧海銀沙,曾經(jīng)中國最火爆的聊天室,已于2017.9.27停止運(yùn)營。

缺點(diǎn)也很明顯:

實(shí)時性差:最壞的情況下,1條消息進(jìn)入隊列后,10s之后才會收到

效率低下:發(fā)消息是一個低頻動作,如果10次輪詢才收到1條消息,請求有效性只有10%,浪費(fèi)了大量服務(wù)器資源

更要命的是,在這種方案下,實(shí)時性與效率是一對不可調(diào)和的矛盾:如果將輪詢周期設(shè)為1/10,將時延縮短到1秒,意味著100次輪詢才會收到1條消息,請求有效性則降為了1%。

方案二、建立長連接

如果要兼顧實(shí)時性和效率,長連接是最佳之選,PC端聊天軟件基本都是使用長連接。網(wǎng)頁端常見的實(shí)現(xiàn)長連接的方式有兩種:

WebSocket

FlashSocket

這兩種方案的細(xì)節(jié)不再展開,ta們均有一定的局限性。

更為通用的方式,是“長輪詢”。

長輪詢,是通過拼裝HTTP短連接來達(dá)到長連接的效果,即保證了消息100%實(shí)時,又最大化的系統(tǒng)效率。

方案三、HTTP長輪詢

HTTP長輪詢的核心在于,瀏覽器與服務(wù)端之間建立了一條“通知連接”,它的特點(diǎn)是:

這是一條browser發(fā)往web-server的HTTP連接

這條連接只用來收取推送通知

不像普通的“請求-響應(yīng)”式HTTP請求,這個HTTP會被服務(wù)端夯住,直到有推送通知到達(dá),或者超過約定的時間

畫外音:對于HTTP請求,為了提高效率,一般來說browser和web-server都會有一些設(shè)置,如果一條HTTP請求長時間沒有數(shù)據(jù)(例如,150秒),會被斷開?!巴ㄖB接”為了不被browser和web-server粗暴斷開,一般會設(shè)置一個約定閾值(例如,小于150秒),由系統(tǒng)返回一個空消息,以便“優(yōu)雅返回”。

更具體的,對于這條“夯住”與“只收推送通知”的“通知連接”,是怎么玩的呢?

場景1,發(fā)起通知連接時,隊列里正好消息,則:

發(fā)起通知連接,正好隊列里有消息

實(shí)時把隊列里的消息帶回

立馬再發(fā)起通知連接

場景二,發(fā)起通知連接時,隊列里消息,則:

發(fā)起通知連接時,隊列里無消息

一直等待,直到觸發(fā)“時間閾值”,返回?zé)o消息

立馬再發(fā)起通知連接

場景三,新消息來時,正好通知連接在,則:

新消息來時,正好有通知連接在

通知連接實(shí)時將消息帶回

立馬再發(fā)起通知連接

上面三個場景的最終狀態(tài),都是“一定,永遠(yuǎn),會有一條通知連接,連接在瀏覽器與服務(wù)器之間”,這樣就能夠保證消息的實(shí)時性。當(dāng)然,有人會說,HTTP的返回與再次發(fā)起會有一個時間差,如果這個時間差,恰巧有新消息過來呢?

場景四,新消息來時,沒有通知連接,則:

新消息來時,沒有通知連接

把新消息放入隊列

最后這個場景,發(fā)生的概率非常小,但也確保了在“HTTP的返回與再次發(fā)起會有一個時間差”內(nèi),消息不會丟失,在通知連接發(fā)起后,消息能夠?qū)崟r返回。

總結(jié)

網(wǎng)頁端收消息,究竟是推還是拉?

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

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

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