WebSocket连接错误Error during WebSocket handshake Unexpected response code 404

WebSocket连接错误Error during WebSocket handshake Unexpected response code 404

一、问题描述

后台SpringBoot使用@ServerEndpoint创建了一个websocket服务端,本地测试的时候一切正常,部署到线上的时候链接报错

1
WebSocket connection to 'ws://xxxx' failed: Error during WebSocket handshake: Unexpected response code: 404

当项目使用域名+端口号的方式访问的时候ws连接正常,而通过nginx反向代理后ws连接就不正常了。

错误的nginx配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
server{
listen 80;
charset utf-8;
server_name ws.xxx.cn;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8087;
}
}

二、原因分析

Websocket握手格式包:

1
2
3
4
5
6
7
8
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协议,里面多了陌生的内容是:

1
2
Upgrade: websocket
Connection: Upgrade

这个就是Websocket的相关的,他会告诉Apache、Nginx等服务器我发起的是websocket请求,不是http!下面的三个参数Sec-WebSocket-Key、Sec-WebSocket-Protocol、Sec-WebSocket-Version作用大概就是验证请求确实是websocket,同时指定协议版本。

三、解决方法

官方地址:http://nginx.org/en/docs/http/websocket.html

nginx配置WebSocket代理

要将客户端和服务器之间的连接从HTTP / 1.1转换为WebSocket,将使用HTTP / 1.1中可用的协议切换机制。

但是,有一个微妙之处:由于“升级”是 逐跳的 标头,因此它不会从客户端传递到代理服务器。使用正向代理,客户端可以使用该CONNECT 方法来规避此问题。但是,这不适用于反向代理,因为客户端不知道任何代理服务器,并且需要对代理服务器进行特殊处理。

从版本1.3.13开始,nginx实施了特殊的操作模式,如果代理服务器返回了代码为101(交换协议)的响应,并且客户端通过以下方式请求协议切换,则允许在客户端与代理服务器之间建立隧道。请求中的“升级”标头。

如上所述,包括“ Upgrade”和“ Connection”的逐跳标头未从客户端传递到代理服务器,因此,为了使代理服务器了解客户端将协议切换到WebSocket的意图,这些标头必须明确传递:

1
2
3
4
5
6
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

默认情况下,如果代理服务器在60秒内未传输任何数据,则连接将关闭。可以使用proxy_read_timeout指令来增加此超时时间 。或者,可以将代理服务器配置为定期发送WebSocket ping帧以重置超时并检查连接是否仍然有效。

如果不配置超时时间,隔一会就会断开 具体超时时间具体要根据业务来调整。最终的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server{
listen 80;
charset utf-8;
server_name ws.xxx.cn;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8087;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_connect_timeout 4s;
proxy_read_timeout 7200s;
proxy_send_timeout 12s;
}
}
-------------已经触及底线 感谢您的阅读-------------

本文标题:WebSocket连接错误Error during WebSocket handshake Unexpected response code 404

文章作者:趙小傑~~

发布时间:2020年03月29日 - 21:49:43

最后更新:2020年03月31日 - 23:59:55

原始链接:https://cnsyear.com/posts/9459878b.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%