问题描述:
使用 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";
复制代码
评论