前阵子小编刚做好了一个websocket项目,可以实现实时聊天,但是最近两天小编突然发现了一个问题,由于我这个项目放到了nginx上做了反向代理,websocket协议连接上后隔一段时间之后会自动断开连接(nginx上一分钟自动快开,本地用外网穿透natapp五分钟自动断开)。刚开始小编并不知道有这么一回事,后来经过各种网上翻找才知道,接下来给大家写出俩解决方法~
1、nginx配置反向代理时会有一个proxy_read_timeout项,意思是连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间),默认60秒,如果你只是想考虑socket协议连接时间问题,可以把这个配置的时间调长一些~
另外还有两个配置项:
proxy_connect_timeout :后端服务器连接的超时时间_发起握手等候响应超时时间;
proxy_send_timeout :后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据;
根据字面意思可以把他们都调长一些,以确保协议连接期间不出现其他错误!
2、配置以上项目后,在配置的时间范围内是不会出现自动断开的错误了,但是如果在该时间段内没有进行任何通讯,到达设定时间范围后还是回自动断开连接,解决办法是在设定时间范围到达之前发心跳包刷新再读时间(就是用此方法重连检测协议连接情况,断开的话进行重连),上代码
该项目小编用的是后台SpringMVC+前台amazeUI框架实现的,借鉴时不要一成不变哦~~~
var lockReconnect = false;
var ws = null;
var url = "ws://"+location.host+"/chatServer/${userid}";
createWebSocket(url);
function createWebSocket(url){
try{
if("WebSocket" in window){
ws = new WebSocket(url);
}else if("MozWebSocket" in window){
ws = new MozWebSocket(url);
}else{
layer.msg("您的浏览器不支持websocket协议,建议使用新版谷歌、火狐等浏览器,请勿使用IE10以下浏览器,360浏览器请使用极速模式,不要使用兼容模式!", { offset: 0});
}
initEventHandle();
}catch(e){
reconnect(url);
console.log(e);
}
}
function initEventHandle(){
ws.onopen = function (evt) {
heartCheck.reset().start();
layer.msg("已经建立连接", { offset: 0});
};
ws.onmessage = function (evt) {
heartCheck.reset().start();
analysisMessage(evt.data); //解析后台传回的消息,并予以展示,此处需要你们自己编写逻辑代码啦
};
ws.onerror = function (evt) {
reconnect(url);
layer.msg("产生异常", { offset: 0});
};
ws.onclose = function (evt) {
reconnect(url);
layer.msg("已经关闭连接," + evt.reason, { offset: 0});
};
}
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
ws.close();
}
function reconnect(url) {
if(lockReconnect) return;
lockReconnect = true;
setTimeout(function () {
//没连接上会一直重连,设置延迟避免请求过多
createWebSocket(url);
lockReconnect = false;
}, 2000);
}
//心跳包
var heartCheck = {
timeout: 240000, //我这里设置的是四分钟发出心跳包,proxy_read_timeout设置的五分钟
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function(){
var self = this;
this.serverTimeoutObj = setTimeout(function(){
ws.send("ping");
self.serverTimeoutObj = setTimeout(function(){
ws.close();
}, self.timeout)
}, this.timeout)
}
}
中间具体的业务逻辑写上你们自己的就可以啦!
经测试该方法可行,在本地通过内网穿透natapp和nginx上都不再自动断开连接~