【问题标题】:Not able to connect to websocket using Nginx and Uvicorn无法使用 Nginx 和 Uvicorn 连接到 websocket
【发布时间】:2021-10-19 23:57:41
【问题描述】:

我用 Django、Uvicorn、Nginx 和 Redis 构建了一个 docker 容器,并且正在使用 django-channels,但是当我运行它时,它说它无法连接到 websocket,这可以在浏览器控制台中看到:

WebSocket connection to 'ws://127.0.0.1:8080/ws/notifications/' failed

当我使用 Django 的 runserver 命令进行开发时它工作正常,但是当我包含 Nginx 和 Uvicorn 时它会中断。

入口点.sh:

gunicorn roomway.asgi:application --forwarded-allow-ips='*' --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker

Nginx 配置:

upstream django {
    server app:8000;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 8080;

    location /static {
        alias /vol/static;
    }

    location /ws/ {
        proxy_pass http://0.0.0.0:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

    location / {
        proxy_pass http://django;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_redirect off;
        proxy_buffering off;
    }
}

settings.py:

CHANNEL_LAYERS={
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('redis', 6379)],  #Redis port
        }
    }
}

处理socket的JS文件:

var wsStart = "ws://"    
var webSocketEndpoint =  wsStart + window.location.host + '/ws/notifications/'
const notificationSocket = new WebSocket(webSocketEndpoint)

asgi.py:

application = ProtocolTypeRouter({
    "http": django_asgi_app,
    "websocket": AuthMiddlewareStack(
        URLRouter([
            url(r'^ws/notifications/', NotificationConsumer.as_asgi()),
            path("ws/<str:room_name>/", ChatConsumer.as_asgi())            
        ])
    )
})

Nginx 用上面的代码抛出这个错误:

[error] 23#23: *4 connect() failed (111: Connection refused) while connecting to upstream, server: , request: "GET /ws/notifications/ HTTP/1.1", upstream: "http://0.0.0.0:8000/ws/notifications/", host: "127.0.0.1:8080"

当我将proxy_pass 更改为http://django 而不是0.0.0.0 时,Nginx 不再抛出该错误,但我在控制台上得到相同的错误。这一次 Django 也抛出了这些警告:

[WARNING] Unsupported upgrade request.       
[WARNING] No supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually.

【问题讨论】:

  • 您是否需要更改 proxy_pass 以将请求发送到您的 django 容器 proxy_pass http://django;?目前你只是将它传递给“0.0.0.0”
  • @lian 我现在试过了,但在控制台上仍然出现同样的错误。虽然这一次,我收到来自 Django 应用程序的警告,上面写着:[WARNING] Unsupported upgrade request。 [警告] 未检测到支持的 WebSocket 库。请使用“pip install uvicorn[standard]”,或手动安装“websockets”或“wsproto”。考虑到我安装了 django-channels,这很奇怪
  • 频道不会为你安装uvicorn,如果你想运行gunicorn/uvcorn你需要安装它
  • 我已经在容器上安装了 gunicorn==20.1.0 和 uvicorn==0.15.0
  • 尝试安装uvicorn[standard],而不是:pip uninstall uvicorn &amp;&amp; pip install uvicorn[standard]。似乎 websocket 支持可能不包含在基本安装中

标签: django docker nginx websocket uvicorn


【解决方案1】:

正如Iain Shelvington 的评论中所指出的,websockets 似乎不包含在 uvicorn 的基本安装中

pip uninstall uvicorn
pip install 'uvicorn[standard]'

【讨论】:

  • 在某些 shell 上,它可能会抱怨找不到包。你必须引用包:pip install 'uvicorn[standard]'
猜你喜欢
  • 1970-01-01
  • 2021-04-25
  • 2013-08-22
  • 2019-08-14
  • 2021-01-27
  • 1970-01-01
  • 2019-07-21
  • 2015-11-10
相关资源
最近更新 更多