详解如何实现在线聊天系统中的实时消息获取

阅读数:58 2019 年 10 月 21 日 13:22

详解如何实现在线聊天系统中的实时消息获取

传统 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 服务建立后端服务

登录华为云,创建弹性云服务器

详解如何实现在线聊天系统中的实时消息获取

输入 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()) + “\n\n”);
10 interval = setInterval(function () {
11 res.write("data: " + (new Date()) + “\n\n”); 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。

登录华为云,首先创建 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

2. 由于 IE 浏览器不支持 Server Sent Event,需要从 github 下载浏览器兼容的 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 填入上面指定位置。在本地用浏览器打开此页面,可以看到页面上显示的时间每秒刷新一次。

以上就是对如何实现在线聊天系统中的实时消息获取的详解,想要了解更多,点击“阅读原文”立即体验一番吧~

本文转载自公众号中间件小哥(ID:huawei_kevin)。

原文链接:

https://mp.weixin.qq.com/s/Blm-IFreKREiKlAXo70qWQ36

评论

发布