詳解如何實現在線聊天系統中的實時消息獲取
全文共3682 字,預計閱讀時間: 10 分鐘
序言
傳統web瀏覽器應用採用客戶端主動請求方式,只有在收到瀏覽器請求時服務端才返回消息,這種模式已經不能滿足日益多樣化的web應用需求,例如:
在線聊天系統:需要實時獲取聊天消息。
實時監控系統:需要實時獲取監控對象狀態。如儀錶讀數、告警信息等。
隨著html技術演進,發展出了多種伺服器推送技術,用於伺服器向瀏覽器客戶端推送消息。
Ajax輪詢
採用Ajax定時向服務端發送請求檢查有無消息更新。網頁定時向伺服器發送請求,若伺服器有消息推送,則返回消息,否則返回空消息,如下圖所示:
這種輪詢方式需要發送大量無效請求,大大消耗了伺服器資源,且推送消息的實時性較低。
Ajax長輪詢
Ajax長輪詢對前面的Ajax輪詢方式做了改進,服務端收到請求後,不再立即返回,而是等待有消息推送時返回。網頁收到服務端返回的消息後,立即發起一個新的請求,等待下一個推送消息。
採用這種方式的服務端實現比前者複雜,需要維護一個客戶端建立的連接列表,當產生對某個客戶端的推送消息後找到對應的連接並發送。優勢是減少了輪詢消耗,發送事件的實時性得到增強。
Server-Send Event
Server-Send Event是html5標準新增的技術,它延用了Ajax長輪詢的思路,並對其進行了一些規範。Server-Send Event讓服務端可以向客戶端流式發送文本消息,並在發送完一個消息後保持請求不結束,連接始終保持。如下圖所示:
網頁調用EventSource介面向伺服器發送請求:
Javascript 代碼
1 var source = new EventSource("http://localhost:8080");
2source.addEventListener("message", function(e) { console.log(e.data); }, false);
伺服器返回的Content-Type頭必須為text/event-stream,且返回完一個消息後不關閉請求,後續消息仍然使用同一個請求返回。瀏覽器會自動以換行符識別每個消息。
響應頭-Java 代碼
1 Content-Type: text/event-stream
2 X-Accel-Buffering: no
響應體-Java 代碼
1 event: userlogin
2 data: {"username": "John123"}
3
4 event: message
5 data: 123
如果服務端返回的消息通過nginx等代理伺服器返回給客戶端時,可能受到nginx緩存機制的影響。某些情況下,nginx會將服務端返回體緩存起來,等待所有返回接受完畢後再統一返回給客戶端,在server-send event情況下將導致客戶端無法及時接收到消息。需要在返回頭中添加X-Accel-Buffering: no,以防止nginx做緩存。
使用華為API gateway提供
Server-Send Event類型的
API服務建立後端服務
登錄華為雲https://console.huaweicloud.com/,創建彈性雲伺服器
輸入apt install nodejs安裝nodejs,使用nodejs創建伺服器,並輸入下列示例代碼。
Javascript 代碼
01 var http = require("http");
02
03 http.createServer(function (req, res) {
04 if (req.url === "/stream") {
05 res.writeHead(200, {
06 "Content-Type":"text/event-stream",
07 "X-Accel-Buffering":"no",
08 });
09 res.write("data: " + (new Date()) + "
");
10 interval = setInterval(function () {
11 res.write("data: " + (new Date()) + "
");12 }, 1000);
13
14 req.connection.addListener("close", function () {
15 clearInterval(interval);
16 }, false);
17 }
18 }).listen(8080);
上面代碼是伺服器每秒向客戶端發送時間的示例。將上面的代碼保存為server.js,然後執行nodejs server.js &
就啟動了監聽在8080埠的伺服器。
添加安全組
將8080埠添加到安全組規則,使得外部可以訪問雲伺服器的8080埠。
創建API
API網關提供從內網訪問雲伺服器的能力,不需要申請公網彈性IP,就可以通過VPC通道開放API。
登錄華為雲https://console.huaweicloud.com/apig/ ,首先創建VPC通道,埠為8080
將彈性雲伺服器添加到VPC通道:
創建API,認證類型選擇APP
「請求Path」填「/stream」,「開啟跨域」選項選擇開啟
創建API完成後,發布API到RELEASE環境。
創建APP並綁定API
在應用管理界面創建一個APP,並綁定剛剛創建的API。
創建OPTIONS方法的API
OPTIONS方法的API是提供給瀏覽器發送跨域請求的預請求使用,同樣選擇開啟跨域(CORS),並將後端配置為Mock。
點完成創建API後,發布API到RELEASE環境。
創建網頁,訪問API
1.要訪問APP認證方式的API,需要通過APP的key和secret生成簽名,才能校驗通過。生成簽名使用下面鏈接下載的javascript SDK
https://console.huaweicloud.com/apig/?agencyId=c65a0db86e514fe298cdc57c6273411a?ion=cn-south-1&locale=zh-cn#/apig/manager/useapi/sdk
2.由於IE瀏覽器不支持Server Sent Event,需要從https://github.com/Yaffle/EventSource/下載瀏覽器兼容的Server Sent Event實現。
搜索並刪除下面四行代碼:
Javascript 代碼
1 if (url.slice(0, 5) !== "data:" &&
2 url.slice(0, 5) !== "blob:") {
3 requestURL = url + (url.indexOf("?", 0) === -1 ? "?" : "&") + "lastEventId="+ encodeURIComponent(lastEventId);
4 }
3.創建index.html,內容如下:
Html 代碼
01
02
03 SSE APP test
04
05
06 SSE APP test
07
08 09
10
11
12
13
29
30
將剛剛創建的APP的AppKey和AppSecret填入上面指定位置。在本地用瀏覽器打開此頁面,可以看到頁面上顯示的時間每秒刷新一次。
以上就是對如何實現在線聊天系統中的實時消息獲取的詳解,想要了解更多,點擊「閱讀原文」立即體驗一番吧~
點我立即體驗
TAG:中間件小哥 |