詳解如何實如今線聊天系統中的實時消息獲取

序言javascript

傳統web瀏覽器應用採用客戶端主動請求方式,只有在收到瀏覽器請求時服務端才返回消息,這種模式已經不能知足日益多樣化的web應用需求,例如:html

在線聊天系統:須要實時獲取聊天消息。html5

實時監控系統:須要實時獲取監控對象狀態。如儀表讀數、告警信息等。java

隨着html技術演進,發展出了多種服務器推送技術,用於服務器向瀏覽器客戶端推送消息。node

 

Ajax輪詢nginx

採用Ajax定時向服務端發送請求檢查有無消息更新。網頁定時向服務器發送請求,若服務器有消息推送,則返回消息,不然返回空消息,以下圖所示:git

這種輪詢方式須要發送大量無效請求,大大消耗了服務器資源,且推送消息的實時性較低。github

 

Ajax長輪詢web

Ajax長輪詢對前面的Ajax輪詢方式作了改進,服務端收到請求後,再也不當即返回,而是等待有消息推送時返回。網頁收到服務端返回的消息後,當即發起一個新的請求,等待下一個推送消息。後端

採用這種方式的服務端實現比前者複雜,須要維護一個客戶端創建的鏈接列表,當產生對某個客戶端的推送消息後找到對應的鏈接併發送。優點是減小了輪詢消耗,發送事件的實時性獲得加強。

 

Server-Send Event

Server-Send Event是html5標準新增的技術,它延用了Ajax長輪詢的思路,並對其進行了一些規範。Server-Send Event讓服務端能夠向客戶端流式發送文本消息,並在發送完一個消息後保持請求不結束,鏈接始終保持。以下圖所示:

 

網頁調用EventSource接口向服務器發送請求:

var source = new EventSource('http://localhost:8080');    

source.addEventListener('message', function(e) { console.log(e.data); }, false);

 

服務器返回的Content-Type頭必須爲text/event-stream,且返回完一個消息後不關閉請求,後續消息仍然使用同一個請求返回。瀏覽器會自動以換行符識別每一個消息。

 

響應頭

Content-Type: text/event-stream    

X-Accel-Buffering: no    

 

響應體

event: userlogin    

data: {"username": "John123"}    

 

event: message    

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建立服務器,並輸入下列示例代碼。

 

var http = require("http");    

   

http.createServer(function (req, res) {    

 if (req.url === "/stream") {    

 res.writeHead(200, {    

 "Content-Type":"text/event-stream",    

 "X-Accel-Buffering":"no",    

 });    

res.write("data: " + (new Date()) + "\n\n");    

 interval = setInterval(function () {    

res.write("data: " + (new Date()) + "\n\n");  12            }, 1000);    

    

req.connection.addListener("close", function () {    

 clearInterval(interval);    

 }, false);    

 }    

 }).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&region=cn-south-1&locale=zh-cn#/apig/manager/useapi/sdk

 

2.因爲IE瀏覽器不支持Server Sent Event,須要從https://github.com/Yaffle/EventSource/下載瀏覽器兼容的Server Sent Event實現。

搜索並刪除下面四行代碼:

if (url.slice(0, 5) !== "data:" &&    

url.slice(0, 5) !== "blob:") {    

requestURL = url + (url.indexOf("?", 0) === -1 ? "?" : "&") + "lastEventId="+ encodeURIComponent(lastEventId);    

 }    

 

3.建立index.html,內容以下:

 <html>    

 <head>    

<title>SSE APP test</title>    

 </head>    

<body>    

SSE APP test    

 <div id="a"></div>    

 <script src="js/eventsource.js"></script>  09    <script src="js/hmac-sha256.js"></script>  

<script src="js/moment.min.js"></script> 

 <script src="js/moment-timezone-with-data.min.js"></script>    

 <script src="signer.js"></script>    

<script>    

 var req = new signer.HttpRequest()    

 req.method = "GET"    

 req.host = "d3da6a917a844df3bd02896496b1b75b.apigw.cn-south-1.huaweicloud.com"    

req.uri = "/stream"    

var sig = new signer.Signer();    

sig.AppKey = "<your app key>"    

sig.AppSecret = "<your app secret>"    

var opts = sig.Sign(req);    

var source = new EventSourcePolyfill("http://d3da6a917a844df3bd02896496b1b75b.apigw.cn-south-1.huaweicloud.com" + req.uri, {    

 headers: opts.headers    

});    

source.onmessage = function (event) {    

document.getElementById("a").innerHTML = event.data;    

 };    

</script>    

 </body>    

</html>   

 

將剛剛建立的APP的AppKey和AppSecret填入上面指定位置。在本地用瀏覽器打開此頁面,能夠看到頁面上顯示的時間每秒刷新一次。

 

以上就是對如何實如今線聊天系統中的實時消息獲取的詳解,想要了解更多,點擊這裏當即體驗一番吧~

相關文章
相關標籤/搜索