Nginx websocket proxy断连问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx websocket proxy断连问题相关的知识,希望对你有一定的参考价值。

参考技术A 由于项目中需要服务端向移动设备主动推送信令,于是引入websocket协议进行移动设备和服务端之间的通信。Demo程序很正常,服务端使用nodejs ws类库起一个websocket服务器,android设备中使用Okhttp3-ws对接,一切都比较正常。但是集成到生产环境kong api gateway后出现了连接一段时间android设备出现java.io.EOFException错误,服务端ws服务器出现1006错误,websocket连接断开的问题。

由于demo程序运行正常,生产环境与demo环境区别在于android设备和服务端之间使用kong api gateway工具进行了proxy,kong是基于nginx的api管理工具,于是问题分析重点锁定gateway转发的过程。

首先抓包比对一下demo环境和生产环境区别。
demo环境wireshark包:

可以看到,GET请求包和协议切换响应包间隔很短。

kong 环境包:

尝试修改了read timeout的时间,果然出现断连的时间随着timeout而变化,应该就是Nginx这个机制导致的。文档中也明确说明了解决方法,在时间间隔小于read timeout的轮询中不断和服务器进行ping包发送来刷新timeout时间。
实际测试,用20秒的间隔不断给服务器发送心跳,可以保持websocket连接不断。
但是还有一个问题,http upgarde包发出去后应该要等http code 101 Switching Protocols这个包回来才算握手完成,才可以建立tcp长连接,但是在nginx环境下这个包60秒后才回来,但是中间数据交互都是正常的,让人匪夷所思。
再仔细看下nginx转发wireshark包,发现http code 101 Switching Protocols包是由3片TCP包组装而成的:

第一帧序号23,找到后发现内容就是服务器响应握手的http报文内容

所以在25帧时实际已经握手完成了,并非在62秒才传包回来。
第二帧:

传递的数据是connected.
这样就和协议描述一致,先完成handshake再transfer data。但是经过nginx抓发的包一直没有结束符,所以导致wireshark在断连得时候才显示该http报完成,此处不知是不是nginx websocket proxy的bug? 如果有大神知道还请指导。

以上是关于Nginx websocket proxy断连问题的主要内容,如果未能解决你的问题,请参考以下文章

配置 Nginx 反向代理 WebSocket

不能使用 nginx 作为 websocket 代理

使用nginx作为websocket的proxy server

015_NGINX作为WebSocket Proxy的设置

nginx 配置 websocket

nginx 反向代理 websockets