如何修复 "Error during WebSocket handshake: Unexpected response code: 400"?
How do I fix the "Error during WebSocket handshake: Unexpected response code: 400"?
我正在使用 Nginx + Gunicorn + Flask_SocketIo + Docker.
我是 运行 一个 Nginx 容器和一个 EC2 实例上的 python/alpine 容器。
我使用 flask_SocketIo 每 5 秒向客户端页面发送一次信息而无需重新加载页面。
我的应用程序已启动,但 运行 但套接字未连接。所以我在客户端看到的错误是:WebSocket 握手期间出错:意外的响应代码:400
我从服务器端的 Nginx 得到的消息是:
**69.xxx.xxx.xxx - - [20/Dec/2020:21:06:54 +0000] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 400 23 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.x.xxxx.xx Safari/537.36" "-"**
我的应用程序做的是:
- 客户端访问 http://domain.com/project ->
- 已建立套接字连接,服务器上的帖子“已连接”->
- 单击按钮后 ->
- 服务器不断发送信息,发布在HTML页面
我试过的:
- 从 uWSGI 切换到 Gunciorn 服务器
- 调整我的 Nginx 代码 socket.io(多个配置)
什么有效:
- 我的 python 个脚本
- 输入域名后网页加载
- 在没有 Nginx 的情况下进行本地测试时,我的代码似乎运行良好。
这是我的 Nginx 配置:
upstream nameOfApp {
server app:8080;
}
server {
listen 80;
server_name 54.xxx.xxx.xx;
server_name www.domain;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://nameOfApp;
}
location /socket.io/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://nameOfApp;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}
这是我的docker-compose
version: "3.7"
services:
app:
build:
context: ./App
dockerfile: Dockerfile
command: gunicorn mainApp.run:app --bind 0.0.0.0:8080
container_name: app
restart: always
environment:
- APP_NAME=CordLte
expose:
- 8080
nginx:
build: ./Nginx
container_name: nginx
restart: always
ports:
- '80:80'
depends_on:
- app
值得一提的是,我在客户端关闭了轮询。
var socket = io({transports: ['websocket'], upgrade: false});
更新 Miguel 的推荐:
我打开了 socket.io 记录器。
app | 627211f5e8984f13a467f051bc560a29: Sending packet MESSAGE data 0
app | 627211f5e8984f13a467f051bc560a29: Received request to upgrade to websocket
nginx | 69.xxx.xxx.xxx - - [21/Dec/2020:11:41:44 +0000] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 400 23 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.x.xxxx.xx Safari/537.36" "-"
app | 129d66e4d815482cb0251c913e6cb004: Sending packet OPEN data {'sid': '129d66e4d815482cb0251c913e6cb004', 'upgrades': [], 'pingTimeout': 60000, 'pingInterval': 25000}
app | 129d66e4d815482cb0251c913e6cb004: Sending packet MESSAGE data 0
app | 129d66e4d815482cb0251c913e6cb004: Received request to upgrade to websocket
nginx | 69.xxx.xxx.xxx - - [21/Dec/2020:11:41:50 +0000] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 400 23 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.x.xxxx.xx Safari/537.36" "-"
这是点击按钮后记录器的结果:
app | 1c0df226c9b14e8c8da8afe9bd1601c7: Sending packet MESSAGE data 2["message",{"data":["678",0]}]
app | 7bda92d2ea9a41c5abd22f4576d6a075: Sending packet MESSAGE data 2["message",{"data":["678",0]}]
app | 1c0df226c9b14e8c8da8afe9bd1601c7: Client is gone, closing socket
app | 1c0df226c9b14e8c8da8afe9bd1601c7: Client is gone, closing socket
app | 7bda92d2ea9a41c5abd22f4576d6a075: Sending packet MESSAGE data 2["message",{"data":["680",0]}]
如果还有什么我可以澄清的,请告诉我
几天后...我发现了我的问题。
我需要在 docker-compose 命令上添加 -k gevent
。我需要添加 gevent 来处理我的事件循环。 Gunicorn 使用同步 worker class 来处理请求,但它可以配置为使用 gevent。
我正在使用 Nginx + Gunicorn + Flask_SocketIo + Docker.
我是 运行 一个 Nginx 容器和一个 EC2 实例上的 python/alpine 容器。
我使用 flask_SocketIo 每 5 秒向客户端页面发送一次信息而无需重新加载页面。
我的应用程序已启动,但 运行 但套接字未连接。所以我在客户端看到的错误是:WebSocket 握手期间出错:意外的响应代码:400
我从服务器端的 Nginx 得到的消息是:
**69.xxx.xxx.xxx - - [20/Dec/2020:21:06:54 +0000] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 400 23 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.x.xxxx.xx Safari/537.36" "-"**
我的应用程序做的是:
- 客户端访问 http://domain.com/project ->
- 已建立套接字连接,服务器上的帖子“已连接”->
- 单击按钮后 ->
- 服务器不断发送信息,发布在HTML页面
我试过的:
- 从 uWSGI 切换到 Gunciorn 服务器
- 调整我的 Nginx 代码 socket.io(多个配置)
什么有效:
- 我的 python 个脚本
- 输入域名后网页加载
- 在没有 Nginx 的情况下进行本地测试时,我的代码似乎运行良好。
这是我的 Nginx 配置:
upstream nameOfApp {
server app:8080;
}
server {
listen 80;
server_name 54.xxx.xxx.xx;
server_name www.domain;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://nameOfApp;
}
location /socket.io/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://nameOfApp;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}
这是我的docker-compose
version: "3.7"
services:
app:
build:
context: ./App
dockerfile: Dockerfile
command: gunicorn mainApp.run:app --bind 0.0.0.0:8080
container_name: app
restart: always
environment:
- APP_NAME=CordLte
expose:
- 8080
nginx:
build: ./Nginx
container_name: nginx
restart: always
ports:
- '80:80'
depends_on:
- app
值得一提的是,我在客户端关闭了轮询。
var socket = io({transports: ['websocket'], upgrade: false});
更新 Miguel 的推荐:
我打开了 socket.io 记录器。
app | 627211f5e8984f13a467f051bc560a29: Sending packet MESSAGE data 0
app | 627211f5e8984f13a467f051bc560a29: Received request to upgrade to websocket
nginx | 69.xxx.xxx.xxx - - [21/Dec/2020:11:41:44 +0000] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 400 23 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.x.xxxx.xx Safari/537.36" "-"
app | 129d66e4d815482cb0251c913e6cb004: Sending packet OPEN data {'sid': '129d66e4d815482cb0251c913e6cb004', 'upgrades': [], 'pingTimeout': 60000, 'pingInterval': 25000}
app | 129d66e4d815482cb0251c913e6cb004: Sending packet MESSAGE data 0
app | 129d66e4d815482cb0251c913e6cb004: Received request to upgrade to websocket
nginx | 69.xxx.xxx.xxx - - [21/Dec/2020:11:41:50 +0000] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 400 23 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.x.xxxx.xx Safari/537.36" "-"
这是点击按钮后记录器的结果:
app | 1c0df226c9b14e8c8da8afe9bd1601c7: Sending packet MESSAGE data 2["message",{"data":["678",0]}]
app | 7bda92d2ea9a41c5abd22f4576d6a075: Sending packet MESSAGE data 2["message",{"data":["678",0]}]
app | 1c0df226c9b14e8c8da8afe9bd1601c7: Client is gone, closing socket
app | 1c0df226c9b14e8c8da8afe9bd1601c7: Client is gone, closing socket
app | 7bda92d2ea9a41c5abd22f4576d6a075: Sending packet MESSAGE data 2["message",{"data":["680",0]}]
如果还有什么我可以澄清的,请告诉我
几天后...我发现了我的问题。
我需要在 docker-compose 命令上添加 -k gevent
。我需要添加 gevent 来处理我的事件循环。 Gunicorn 使用同步 worker class 来处理请求,但它可以配置为使用 gevent。