SSE 消息推送 异常解决方案
部分问题解决方案
1、SSE 报错会不会持续建立连接?
连接后报错可以重新连接,重新连接间隔由服务端传输字段设定
2、主动写销毁方法与页面直接关闭是否有性能区别?
* 关闭 MES 菜单标签页不会自动关闭 SSE 连接 (可在页面销毁前调用方法关闭 SSE 连接)
* 关闭浏览器标签页会关闭
* 如果关闭 MES 菜单标签页不会自动关闭怎么处理?
在页面代码中写上,在页面销毁前关闭通道 和关闭浏览器标签页没有性能区别
methods:{
getSSE() {
let that = this;
this.source = new EventSource("http://10.1.1.133:8081/sseMsg/pushWeb/admin");
this.source.addEventListener("message", (e) => {
console.log(e);
});
},
},
...
beforeDestroy() {
this.source.close()
// 调用SSE关闭方法
} ...
3、浏览器会有最大连接限制 6 个连接
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events/Using_server-sent_events
4、SSE 管道向后台请求时,是否可以控制频次(为避免对服务器造成压力),频次可能是服务端控制的,待确认?
重连时间可由 retry 字段返回 默认是 3s
可尝试使用 SseEmitter https://www.cnblogs.com/jun1019/p/10886079.html
达摩院 SSE http://119.96.220.140:9099/article/1629195920546
5、后台使用了 return ’data’代码语句,是否会导致每次都在请求后台,重新建立连接
1、return data 方式不合理,应使用类似这种解决方式
2、如果使用 return 数据传输前台后 return 导致通道关闭触发 SSE 断线重连 会继续服务端发送请求建立连接
* return data
参考解决办法 : https://www.jianshu.com/p/100b82730e15 修改后,连接成功后只会存在一个持续的 SSE 连接
* 修改后的
6、异常重连机制
两种情况会导致浏览器重新发起连接:一种是时间间隔到期,二是由于网络错误等原因,导致连接出错,三是请求建立通道失败也会重连
重连会触发事件: open 建立连接时触发;error 与连接无法建立时触发)
服务端可以用 retry 字段,设置浏览器重新发起连接的时间间隔。默认为 3s (需要通道正常连接后,才能获取服务端设置的 retry 属性)retry: 10000\ndata: ${数据} \n\n
重连次数限制
* 可在前台设置监听 error 次数
const source = new EventSource("/sseMsg/pushWeb/admin");
source.onopen = (e) => { console.log("open", e); };
source.onmessage = (e) => { console.log("message", e); // 处理业务数据
};
...
// 在报错监听上 添加次数限制
source.onerror = (e) => {
let times = 5 // 设置重连次数 可结合retry使用
times--
if (times == 0) {
source.close() // 关闭SSE通道
times = 5
}
};
SSE 介绍与使用
使用说明参照:达摩院论坛:服务器推送客户端方案 SSE 在规则引擎中的应用
* SSE 接收数据的固定格式 retry:${毫秒数}\ndata:${返回数据}\n\n
* retry: 指每隔多久重连一次服务器, 谷歌默认是 3000 毫秒
* data: 是指要接收的数据
* SSE 触发重连情况:
* 时间间隔到期;
* 网络错误等原因,导致连接出错;
* 请求建立通道失败也会重连;
* 如后台异常或网络故障,两种方案
* 前台限制重连次数
* 优点:可及时停止 SSE 重连机制
* 缺点:设置重连次数需要手动建立连接
* 服务端断开期间,一直会重复建立连接,当达到限制次数时会关闭 SSE 通道,当服务端连接上后,需要手动去建立 SSE 连接;(通常方法:刷新页面重新建立连接)
* 不限制重连次数
* 优点:服务器断开期间,会尝试重连,当服务恢复后,会自动连接上服务器
* 缺点:服务器断开期间,会重复建立连接,如有异常日志记录情况会造成日志量过大
// 在报错监听上 添加次数限制
source.onerror = (e) => {
let times = 5
// 设置重连次数 可结合retry使用
times--
if (times == 0) {
source.close()
// 关闭SSE通道
times = 5
}
};
大屏看板数据推送方案
<script>
export default {
methods:{
getSSE() {
// 建立SSE连接通道
let that = this
this.source = new EventSource("SSE连接");
// 有数据传来时触发
this.source.addEventListener("message", (e) => {
console.log(e);
});
// 出现网络错误,或服务端连接失败时触发
this.source.addEventListener("error", (e) => {
// 限制重连次数方法
// let times = 5
// 设置重连次数 可结合retry使用
// times--
// if (times == 0) {
// that.source.close()
// 关闭SSE通道
// times = 5
// }
});
},
},
mounted(){
this.getSSE()
},
beforeDestroy() {
this.source.close() // 调用SSE关闭方法
}
}
</script>
app 数据推送方案
使用说明参照: 达摩院论坛:App SSE 消息推送
SSE 连接跨域
样例: nginx
配置
upstream sse {
ip_hash;
#keepalive 300;
#sticky;
server 192.168.40.214:8081; // SSE服务地址
}
location /sseServeUrl {
proxy_pass http://sse;
tcp_nodelay on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Handle request
}
前端使用:
// index.html
...
window.SITE_CONFIG["sseServerUrl"] = "/sseServeUrl";
...
SSE 使用
...
source = new EventSource(window.SITE_CONFIG["sseServerUrl"] + "/*****/****"); // 配置接口
...
如果遇到首次请求事件间距过长 或长时间请求不到超时 需添加
参考链接 :https://stackoverflow.com/questions/13672743/eventsource-server-sent-events-through-nginx
location /sseServeUrl {
proxy_pass http://sse;
tcp_nodelay on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Handle request
# 下面代码处理超时或长时间请求不到
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
}