【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

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

  • 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:221470

评论

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

阿里前端常考vue面试题汇总

bb_xiaxia1998

Vue 前端

推荐系统[八]算法实践总结V0:腾讯音乐全民K歌推荐系统架构及粗排设计

汀丶人工智能

自然语言处理 推荐系统 推荐算法 搜索算法

说说Vue响应式系统中的Watcher和Dep的关系-面试进阶

bb_xiaxia1998

Vue 前端

湖仓一体电商项目(二十一):数据发布接口和数据可视化

Lansonli

湖仓一体电商项目

一块GPU搞定ChatGPT;ML系统入坑指南;理解GPU底层架构

OneFlow

人工智能 深度学习

前端必会面试题指南

loveX001

JavaScript 前端

react的jsx和React.createElement是什么关系?面试常问

beifeng1996

前端 React

互联网大厂Java 最常见的 1100+ 面试题汇总(金三银四面试必备)

架构师之道

java面试

EasyRecovery16汉化版数据恢复软件

茶色酒

EasyRecovery16

高级前端必会面试题(边面边更)

loveX001

JavaScript 前端

有趣的`events_statements_current`表问题

GreatSQL

MySQL greatsql greatsql社区

实现一个简单的Database11(译文)

GreatSQL

MySQ percona server greatsql greatsql社区

DevOps 与 FinOps:二者可以协同吗?

SEAL安全

DevOps FinOps 企业号 2 月 PK 榜

百度前端高频react面试题(持续更新中)

beifeng1996

前端 React

用于双目重建中的GPU编程:julia-cuda

京东科技开发者

机器学习 gpu 编码 Code julia

瓴羊Quick BI智能报表打破“中式”报表限制,提速增效

夏日星河

CleanMyMac X4.13mac电脑免费系统优化软件

茶色酒

CleanMyMac X4.13

React面试:谈谈虚拟DOM,Diff算法与Key机制

beifeng1996

前端 React

学生信息管理系统

lory(侯保国)

一步步实现React-Hooks核心原理

helloworld1024fd

JavaScript 前端

前端一面react面试题(持续更新中)

beifeng1996

前端 React

INFINI 产品更新|Loadrun 首发亮相

极限实验室

console Gateway infini loadgen loadrun

富表智能可视化设计工具(FusionView)

风清扬

数据分析 低代码 可视化 数据大屏 数据可视化拖拽

这些js原型及原型链面试题你能做对几道

loveX001

JavaScript 前端

谈谈前端性能优化-面试版

loveX001

JavaScript 前端

解密游戏推荐系统的建设之路

vivo互联网技术

架构 推荐系统

首届OpenHarmony技术峰会携手产业界与学术界,共建技术与人才生态

Geek_2d6073

快来解锁小程序蓝牙开发技能

南城FE

小程序 微信 前端开发 uniapp 蓝牙

能不能手写Vue响应式?前端面试进阶

bb_xiaxia1998

Vue 前端

零代码(低代码)工作流引擎(cube-flowable)

风清扬

低代码 工作流引擎 动态表单

人人看得懂的ChatGPT技术原理解析

Baihai IDP

人工智能 自然语言处理 NLP 大模型 12 月 PK 榜 ChatGPT

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