網(wǎng)頁(yè)端收消息的三種方式
場(chǎng)景描述

在網(wǎng)頁(yè)端登錄的用戶A,有兩類發(fā)送給他的消息:
- 系統(tǒng)發(fā)給A的“系統(tǒng)通知”;
- 用戶發(fā)給A的“聊天消息”;
系統(tǒng)側(cè),一般來(lái)說(shuō),對(duì)每一個(gè)接受消息的用戶都有一個(gè)“待收消息”的隊(duì)列,里面存放了需要給這個(gè)用戶的所有消息。
用戶A,如果是在網(wǎng)頁(yè)端登錄,有幾種常見(jiàn)的收取消息的方式呢?
常見(jiàn)的方案有3種。
方案一、輪詢拉取

輪詢拉取,這是最容易想到的實(shí)現(xiàn)方式:
- 網(wǎng)頁(yè)端起一個(gè)timer,每個(gè)一段時(shí)間(例如10秒),發(fā)起一個(gè)輪詢請(qǐng)求,拉取隊(duì)列里的消息;
- 如果隊(duì)列里有消息,就返回消息;
- 如果隊(duì)列里無(wú)消息,就10秒后再次輪詢;
這種方式的優(yōu)勢(shì)是:實(shí)現(xiàn)簡(jiǎn)單,直觀且,容易理解,互聯(lián)網(wǎng)興起時(shí),人數(shù)不多的聊天室就是這么玩的。
畫(huà)外音:我最早玩的聊天室,是創(chuàng)辦于1996年的互聯(lián)網(wǎng)老站碧海銀沙,大家聽(tīng)過(guò)嗎?
缺點(diǎn)也很明顯:
- 實(shí)時(shí)性差:最壞的情況下,1條消息進(jìn)入隊(duì)列后,10s之后才會(huì)收到;
- 效率低下:發(fā)消息是一個(gè)低頻動(dòng)作,如果10次輪詢才收到1條消息,請(qǐng)求有效性只有10%,浪費(fèi)了大量服務(wù)器資源;
方案二、建立長(zhǎng)連接
如果要兼顧實(shí)時(shí)性和效率,長(zhǎng)連接是最佳之選,PC端聊天軟件基本都是使用長(zhǎng)連接。
網(wǎng)頁(yè)端常見(jiàn)的實(shí)現(xiàn)長(zhǎng)連接的方式有兩種:
- WebSocket;
- FlashSocket;
這兩種方案的細(xì)節(jié)不再展開(kāi)。
方案三、HTTP長(zhǎng)輪詢
長(zhǎng)輪詢,是通過(guò)拼裝HTTP短連接來(lái)達(dá)到長(zhǎng)連接的效果,即保證了消息100%實(shí)時(shí),又最大化的系統(tǒng)效率。

HTTP長(zhǎng)輪詢的核心在于,瀏覽器與服務(wù)端之間建立了一條“通知連接”,它的特點(diǎn)是:
- 這是一條browser發(fā)往web-server的HTTP連接;
- 這條連接只用來(lái)收取推送通知;
- 不像普通的“請(qǐng)求-響應(yīng)”式HTTP請(qǐng)求,這個(gè)HTTP會(huì)被服務(wù)端夯住,直到有推送通知到達(dá),或者超過(guò)約定的時(shí)間;
更具體的,對(duì)于這條“夯住”與“只收推送通知”的“通知連接”,是怎么玩的呢?

場(chǎng)景1,發(fā)起通知連接時(shí),隊(duì)列里正好有消息,則:
- 發(fā)起通知連接,正好隊(duì)列里有消息;
- 實(shí)時(shí)把隊(duì)列里的消息帶回;
- 立馬再發(fā)起通知連接;

場(chǎng)景二,發(fā)起通知連接時(shí),隊(duì)列里無(wú)消息,則:
- 發(fā)起通知連接時(shí),隊(duì)列里無(wú)消息;
- 一直等待,直到觸發(fā)“時(shí)間閾值”,返回?zé)o消息;
- 立馬再發(fā)起通知連接;

場(chǎng)景三,新消息來(lái)時(shí),正好有通知連接在,則:
- 新消息來(lái)時(shí),正好有通知連接在;
- 通知連接實(shí)時(shí)將消息帶回;
- 立馬再發(fā)起通知連接;
上面三個(gè)場(chǎng)景的最終狀態(tài),都是“一定,永遠(yuǎn),會(huì)有一條通知連接,連接在瀏覽器與服務(wù)器之間”,這樣就能夠保證消息的實(shí)時(shí)性。
總結(jié)
網(wǎng)頁(yè)端收消息,一般有三種模式:
(1) 最容易想到的是拉,但實(shí)時(shí)性和效率是一對(duì)無(wú)法調(diào)和的矛盾;
(2) 最佳的方式是推:
- WebSocket和FlashSocket是建立TCP長(zhǎng)鏈接
- 也可以長(zhǎng)輪詢,通過(guò)HTTP短連接拼裝長(zhǎng)連接,具體是通過(guò)“夯住”“只收推送通知”的“通知連接”來(lái)實(shí)現(xiàn)的,能夠做到消息的實(shí)時(shí)性到達(dá)
知其然,知其所以然。
思路比結(jié)論更重要。

























