写点什么

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

  • 2019-10-21
  • 本文字数:2677 字

    阅读完需:约 9 分钟

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

传统 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


03SSE APP test


04


05


06 SSE APP test


07


<br/>14 var req = new signer.HttpRequest()<br/>15 req.method = “GET”<br/>16 req.host = “<a href="http://d3da6a917a844df3bd02896496b1b75b.apigw.cn-south-1.huaweicloud.com">d3da6a917a844df3bd02896496b1b75b.apigw.cn-south-1.huaweicloud.com</a>”<br/>17 req.uri = “/stream”<br/>18 var sig = new signer.Signer();<br/>19 sig.AppKey = “<your app key>”<br/>20 sig.AppSecret = “<your app secret>”<br/>21 var opts = sig.Sign(req);<br/>22 var source = new EventSourcePolyfill(“<a href="http://d3da6a917a844df3bd02896496b1b75b.apigw.cn-south-1.huaweicloud.com">http://d3da6a917a844df3bd02896496b1b75b.apigw.cn-south-1.huaweicloud.com</a>” + req.uri, {<br/>23 headers: opts.headers<br/>24 });<br/>25 source.onmessage = function (event) {<br/>26 document.getElementById(“a”).innerHTML = event.data;<br/>27 };<br/>28


将刚刚创建的 APP 的 AppKey 和 AppSecret 填入上面指定位置。在本地用浏览器打开此页面,可以看到页面上显示的时间每秒刷新一次。


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


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


原文链接:


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


2019-10-21 13:221821

评论

发布
暂无评论
发现更多内容

汇率市场大幅波动,用友BIP全球司库助力企业外汇避险

用友BIP

金融 外汇避险

2023年2月国产数据库大事记-墨天轮

墨天轮

数据库 opengauss TiDB oceanbase 国产数据库

3 月 9 日「融云 2023 政企数智办公新品巡展 · 北京站」邀您入席!

融云 RongCloud

产品 数字化 政企

CNStack 助推龙源电力扛起“双碳”大旗

阿里巴巴云原生

阿里云 云原生 CNStack

车载小程序发展现状:使用环境、用户体验、应用场景及未来趋势

没有用户名丶

小程序化

ChatGPT 未来发展趋势 | 社区征文

魏铁锤

ChatGPT

开放下载丨云原生架构容器&微服务优秀案例集

阿里巴巴云原生

阿里云 容器 微服务 云原生

瓴羊Quick BI数据大屏真不错,优势尽显!

流量猫猫头

2023两会看点:SaaS

ToB行业头条

博睿“她”力量 :这份专业值得信赖

博睿数据

博睿数据 节日祝福

瓴羊Quick BI真心不错,已获得官方认可!

对不起该用户已成仙‖

IoT物联网设备OTA固件升级开发实践——设备管理运营类

阿里云AIoT

物联网

MASA MAUI Plugin (十)iOS消息推送(原生APNS方式)

MASA技术团队

blazor MASA MAUI Xamarin

数字化转角,遇见未来新模式

鼎道智联

及刻周边惠:拥抱HarmonyOS原子化服务

HarmonyOS开发者

HarmonyOS

大咖说·阿里研究院|数实融合的第三次浪潮

大咖说

如何判断多账号是同一个人?用图技术搞定 ID Mapping

NebulaGraph

图数据库 风险控制 安全控制

Meta Force佛萨奇2.0合约开发系统源码部署

薇電13242772558

智能合约

bucket表:数仓存算分离中CU与DN解绑的关键

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 3 月 PK 榜

CNStack 多集群服务:基于 OCM 打造完善的集群管理能力

阿里巴巴云原生

阿里云 云原生 kubenetes 集群管理

探索ChatGPT技术在文本生成、机器翻译领域的简单应用 | 社区征文

兴科Sinco

人工智能 机器翻译 OpenAPI openai ChatGPT

直播预约丨 微服务x容器开源开发者 Meetup 北京站回顾 & PPT 下载

阿里巴巴云原生

阿里云 容器 微服务 云原生

携程 x TiDB丨应对全球业务海量数据增长,一栈式 HTAP 实现架构革新

PingCAP

数据库 TiDB

从小程序容器和微服务架构的结合,看未来应用程序开发的主流方式

没有用户名丶

秒懂算法 | DP概述和常见DP面试题

TiAmo

算法 DP算法

百度智能云首批通过信通院MLOps旗舰级评测 全面加速文心一言产业落地

极客天地

解密数仓高可用failover流程

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 3 月 PK 榜

如何通过C#/VB.NET代码在Word中插入或删除脚注

在下毛毛雨

C# .net word 脚注

科技和女性的今天,《赛博格宣言》半个世纪前就预言了

脑极体

赛博格 女性

如何规范 RESTful API 的业务错误处理

江湖十年

Go 后端 Error RESTful API

“中国的ChatGPT”真的要来了吗?

科技热闻

详解如何实现在线聊天系统中的实时消息获取_文化 & 方法_余洲_InfoQ精选文章