nginx代理WebSocket时自动断开连接

前阵子小编刚做好了一个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上都不再自动断开连接~

你可能感兴趣的:(前端)