19

SpringBoot- 技术专题 -Websocket+Nginx 出现 404 问题

 3 years ago
source link: https://xie.infoq.cn/article/7cba4c63789de88120a0fe113
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

问题描述:

使用websocket往商家管理系统发送消息。在本地测试没有任何问题,但是部署到centos服务器上之后一直报错404。总结了网上很多解决方法都不行,网上讨论的都是说tomcat版本太低,因为websocket需要tomcat7.0以上才支持。

解决思路:

排除了tomcat问题,jdk版本也是1.8+,websocket部署到服务器上还是404,网上还有人说是tomcat的jar包和项目jar冲突,可是我springboot项目使用的内嵌tomcat,于是我利用Maven Helper(非常好用的idea插件)查看了下依赖发现并没有冲突。卡在这里很久,我特地看了下websocket请求格式:

Websocket握手格式:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com12345678

这请求类似http协议,里面多了陌生的内容是:

Upgrade: websocket
Connection: Upgrade12

当时一脸懵逼,这是什么玩意啊?然后我就百度了下,原来这个就是Websocket的核心,他会告诉Apache、Nginx等服务器我发起的是websocket请求,不是http!下面的三个参数Sec-WebSocket-Key、Sec-WebSocket-Protocol、Sec-WebSocket-Version作用大概就是验证请求确实是websocket,同时指定协议版本吧。

这时候我恍然大悟!我的项目使用了nginx做了转发,那么会不会是因为我没有配置nginx响应websocket请求呢?答案是肯定的!

配置nginx反向代理响应webSocket请求

需要在代理的请求配置中加入下面的配置:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";12

nginx配置如下:

server {
listen 80;
server_name localhost;
#charset koi8-r;

location / {
root /usr/java/myproject/sell;
index index.html index.htm;
}

location /sell/ {
proxy_pass http://127.0.0.1:8081/sell/;
}

location /sell/webSocket {
proxy_pass http://127.0.0.1:8081/sell/webSocket;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}12345678910111213141516171819

这段配置就是把所有的/sell下的请求转到8081端口处理,把/sell/webSocket请求转发到指定的请求接口,发现404错误消失,webSocket服务也可以访问到。但是出现了一个新的问题就是,webSocket连接后没有保持连接,大约一分钟之后就会断开,原因是因为在第一次请求后到第二次请求到来的时间超过了默认的最大时间,超时了。这里提供一个解决思路:

需要配置的三个核心参数:

proxy_connect_timeout 4s;
proxy_read_timeout 7200s;
proxy_send_timeout 12s; 123

proxy_read_timeout是服务器对连接等待的最大时间,也就是说,当你webSocket使用nginx转发的时候,用上面的配置来说,如果72000秒内没有通讯,依然是会断开的,你可以按照需求来设定。

比如说,我这里设置了7200s(2小时),那么如果我2小时内有通讯,或者2小时内有心跳的话,是可以保持连接不中断的。

我这里之所以这么设置,是考虑到了具体的业务情况,2小时比较合适。最终的配置如下:

server {
listen 80;
server_name localhost;
#charset koi8-r;

location / {
root /usr/java/myproject/sell;
index index.html index.htm;
}

location /sell/ {
proxy_pass http://127.0.0.1:8081/sell/;
}

location /sell/webSocket {
proxy_pass http://127.0.0.1:8081/sell/webSocket;
proxy_connect_timeout 4s;
proxy_read_timeout 7200s;
proxy_send_timeout 12s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK