消息推送是針對 Web 應用開發(fā)領域的技術(shù),指服務端以主動方式將信息送達客戶端。主要用于提升用戶體驗,避免用戶刷新頁面從服務端拉取數(shù)據(jù)。例如 Web 郵件中自動出現(xiàn)剛收到的郵件項,Web 即時通訊自動提示新到消息等應用場景。
要實現(xiàn)消息推送機制,涉及兩方面的內(nèi)容:
可以使用套接字接口進行全雙工通訊??梢酝ㄟ^ Flash XMLSocket、Java Applet 技術(shù)實現(xiàn)。
但由于實現(xiàn)方案與廠商技術(shù)綁定過緊,不屬于 Web 標準化范疇,并且存在一些限制(通訊端口開啟安全、客戶端插件),這里不進行描述。
目前的 Web 應用是基于 HTTP 協(xié)議的,其規(guī)定了請求-響應的處理模型,位于應用層的單工通訊模式使得純粹意義上的服務端推送方式變得難以實現(xiàn)。
為了基于 HTTP 協(xié)議進行“推送”實現(xiàn),可由客戶端發(fā)起 HTTP 請求輪詢,服務端在請求后返回響應。
根據(jù)輪詢時間、請求處理方式,分為以下三種推。
客戶端一般以定時方式發(fā)起請求,服務端處理后返回響應。
客戶端發(fā)起請求后服務端將該請求掛起(不返回響應),直到超時、異?;蛐枰幚眄憫ㄍ苾?nèi)容)才返回??蛻舳耸盏巾憫笤俅握埱螅摧喸儯┓斩耍⑻幚眄憫?。
客戶端發(fā)起請求后服務器端處理請求,并通過 HTTP 流一直向客戶端寫入數(shù)據(jù),直到超時或異常才返回響應。連接斷開后客戶端再次請求服務端,屬于長輪詢的一種。
這是標準化的客戶端全雙工通訊規(guī)范,但由于目前服務端規(guī)范尚未成型,且考慮到現(xiàn)有客戶端對 HTML 5 的支持有限,這里不進行描述。
上述介紹是針對瀏覽器客戶端的,在實際應用場景中,還需要考慮其他客戶端支持,例如 iOS、Android 等。
在移動客戶端方面,需要考慮如下幾點。
不同客戶端本地 APIs 接口存在差異,但都支持基本的 HTTP 協(xié)議。直接基于 HTTP 協(xié)議進行開發(fā)可將差異最小化。
通訊信道打開后不一定能長時間維護,客戶端與服務端的狀態(tài)管理復雜。
需要盡量最小化網(wǎng)絡流量,提升移動客戶端可用性。
消息是系統(tǒng)或組件間通訊的一種低耦合方式,是系統(tǒng)級異步架構(gòu)的基礎。
在 Web 消息推送中,服務端管理應用狀態(tài),當狀態(tài)發(fā)生變遷時需要通知客戶端,完成消息推送。
需要重點關(guān)注如下技術(shù)點:
Web 層考慮采用開源組件 Pushlets 進行實現(xiàn)。
Pushlets 基于 HTTP 協(xié)議的發(fā)布/訂閱模型,提供了 Poll(輪詢)、Pull(拉)兩種推方式實現(xiàn)。其中 Pull 即長輪詢方式,當有消息時就返回。
使用 AJAX 客戶端,較為靈活,便于封裝。
服務層消息服務采用應用服務器 JMS 中間件。通過發(fā)布/訂閱模型實現(xiàn)狀態(tài)同步。
保存推送多的消息記錄,用于客戶端刷新時/多客戶端查找消息。
userId | createdTime | lastGetTime | clients | msg | type | timeout | targetSys | srcSys | …. | |
xxx | xxx | xxx | [“pc”, “iOS”] | {} | 公告 | 3天 | OA | OA |
消息體使用 JSON 字符串存放于 msg 字段中。其余字段可根據(jù)通用性進行抽取,比如用戶名等。
消息監(jiān)聽器接收到消息時推 Pushlets,并進行記錄寫入(記錄 lastGetTime 為寫入時間,表示這條消息已經(jīng)推送過)。
設置定時任務對超時記錄進行刪除。
JMS 消息系統(tǒng)為單獨的通訊總線服務獨立于應用系統(tǒng),Pushlets 為應用系統(tǒng)中的一個組件。
消息表管理組件提供消息新增,以及對推送過的消息記錄的查詢、刪除。