springboot + websocket + linux服务器(nginx)404问题解决

问题描述:

最近基于springboot做一个微信公众号,内嵌一个小的购物商城系统,用户下单后,使用websocket往商家管理系统发送消息。在本地测试没有任何问题,但是部署到centos服务器上之后一直报错404。总结了网上很多解决方法都不行,网上讨论的都是说tomcat版本太低,因为websocket需要tomcat7.0以上才支持。但是我是用springboot+maven搭建的项目,使用的是springboot内嵌的tomcat服务器,我查看了maven,发现tomcat版本是8.0+。那么就不是tomcat版本问题了。

解决思路:

排除了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.com

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

Upgrade: websocket
Connection: Upgrade

当时一脸懵逼,这是什么玩意啊?然后我就百度了下,原来这个就是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";

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";
}

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

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

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";
}

问题解决,坑爹啊!

你可能感兴趣的:(后台技术)