无法使用 django-channels 连接到 websocket,docker 上的 nginx 作为服务
Posted
技术标签:
【中文标题】无法使用 django-channels 连接到 websocket,docker 上的 nginx 作为服务【英文标题】:Can not connect to websocket using django-channels , nginx on docker as services 【发布时间】:2017-09-02 07:10:47 【问题描述】:我正在使用 docker compose 构建一个以 django、nginx 作为服务的项目。当我启动 daphne 服务器并且客户端尝试连接到 websocket 服务器时,我收到此错误:
*1 recv() failed (104: Connection reset by peer) while reading response header from upstream
客户端显示这个
failed: Error during WebSocket handshake: Unexpected response code: 502
这是我的 docker-compose.yml
version: '3'
services:
nginx:
image: nginx
command: nginx -g 'daemon off;'
ports:
- "1010:80"
volumes:
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
- .:/makeup
links:
- web
web:
build: .
command: /usr/local/bin/circusd /makeup/config/circus/web.ini
environment:
DJANGO_SETTINGS_MODULE: MakeUp.settings
DEBUG_MODE: 1
volumes:
- .:/makeup
expose:
- '8000'
- '8001'
links:
- cache
extra_hosts:
"postgre": 100.73.138.65
Nginx:
server
listen 80;
server_name thelab518.cloudapp.net;
keepalive_timeout 15;
root /makeup/;
access_log /dev/stdout;
error_log /dev/stderr;
location /api/stream
proxy_pass http://web:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $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-Host $server_name;
location /
try_files $uri @proxy_to_app;
location @proxy_to_app
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://web:8000;
还有马戏团的 web.ini 文件:
[watcher:web]
cmd = /usr/local/bin/gunicorn MakeUp.wsgi:application -c config/gunicorn.py
working_dir = /makeup/
copy_env = True
user = www-data
[watcher:daphne]
cmd = /usr/local/bin/daphne -b 0.0.0.0 -p 8001 MakeUp.asgi:channel_layer
working_dir = /makeup/
copy_env = True
user = root
[watcher:worker]
cmd = /usr/bin/python3 manage.py runworker
working_dir = /makeup/
copy_env = True
user = www-data
【问题讨论】:
客户端配置是什么样的,您使用的是哪个客户端(socket.io、WebSocket API 等)? 您找到解决方案了吗?正常的 HTTP 请求是否有效?我想我有同样的问题,我仍在寻找解决方案。谢谢 【参考方案1】:正如stated in the fine manual 一样,要成功运行Channels,您需要有一个实现ASGI 协议的专用应用服务器,例如提供的daphne
整个 Django 执行模型已经用 Channels 进行了更改,因此有单独的“接口服务器”负责接收和发送消息,例如,WebSockets 或 HTTP 或 SMS,以及运行实际的“工作服务器”代码(可能在不同的服务器或虚拟机或容器上或......)。两者通过一个“通道层”连接起来,该通道层来回传递消息和回复。
当前实现提供了 3 个通道层,用于在接口服务器和工作服务器之间进行 ASGI 通信:
内存通道层,主要用于运行测试服务器(它是单进程) 基于 IPC 的通道层,可用于在同一服务器上运行不同的工作器 基于 redis 的通道层,应该用于大型生产站点,能够将接口服务器连接到多个工作服务器。您可以像对 DATABASES:: 一样配置它们
CHANNEL_LAYERS =
"default":
"BACKEND": "asgi_redis.RedisChannelLayer",
"ROUTING": "my_project.routing.channel_routing",
"CONFIG":
"hosts": [("redis-channel-1", 6379), ("redis-channel-2", 6379)],
,
,
当然,这意味着您的 docker 配置必须更改并添加一个或多个接口服务器,而不是 nginx
(即使在这种情况下,您需要在具有所有可能连接问题的不同端口),并且很可能是连接所有这些问题的 redis 实例。
这反过来意味着在 circus 和 nginx 可以支持 ASGI 之前,将无法将它们与 django-channels 一起使用,或者这种支持仅适用于系统的常规 http 部分。
您可以在Deploying section of the official documentation找到更多信息。
【讨论】:
【参考方案2】:您似乎在端口 8001 上盯着 daphne
,并试图在 docker-compose 中公开端口 8000 和 8001。端口 8000 未指向任何服务器(daphne
在 8001 上)。在您的 nginx 中,请将代理设置为 8001 端口,并在 docker-compose 中仅公开端口 8001。
我创建了一个简单的示例,如何在 github 上设置它,我有代理到 asgi 和 wsgi 服务器,但你只能使用 asgi 服务器:
nginx:
upstream app
server wsgiserver:8000;
upstream ws_server
server asgiserver:9000;
server
listen 8000 default_server;
listen [::]:8000;
client_max_body_size 20M;
location /
try_files $uri @proxy_to_app;
location /tasks
try_files $uri @proxy_to_ws;
location @proxy_to_ws
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_pass http://ws_server;
location @proxy_to_app
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
docker-compose.yml:
version: '2'
services:
nginx:
extends:
file: docker-common.yml
service: nginx
ports:
- 8000:8000
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
volumes_from:
- asgiserver
asgiserver:
extends:
file: docker-common.yml
service: backend
entrypoint: /app/docker/backend/asgi-entrypoint.sh
links:
- postgres
- redis
- rabbitmq
expose:
- 9000
wsgiserver:
extends:
file: docker-common.yml
service: backend
entrypoint: /app/docker/backend/wsgi-entrypoint.sh
links:
- postgres
- redis
- rabbitmq
expose:
- 8000
【讨论】:
以上是关于无法使用 django-channels 连接到 websocket,docker 上的 nginx 作为服务的主要内容,如果未能解决你的问题,请参考以下文章
Django Channels Consumer 未连接到 websocket
无法使用php连接错误连接到mysql:无法连接到'localhost'(10061)上的MySQL服务器[重复]
为啥即使使用 Colab Pro 帐户也无法连接到 GPU 后端?
PEAR Mail 无法连接到 Gmail SMTP,无法连接到套接字