部署期间的 django 通道问题

django channel issue during deployment

我正在使用 Django Channels 并使用 NGINX+Gunicorn+Uvicorn 进行部署,并遵循 Digital Ocean 的教程(即 https://www.digitalocean.com/community/tutorials/how-to-set-up-an-asgi-django-app-with-postgres-nginx-and-uvicorn-on-ubuntu-20-04

当我尝试使用以下命令在没有 NGINX 的情况下 运行 站点 @ www.myproject.com:8000 时,我没有发现任何问题:

gunicorn --bind 0.0.0.0:8000 myproject.asgi -w 4 -k uvicorn.workers.UvicornWorker

但是,当我使用 NGINX 部署时,除了使用 django 频道的聊天功能页面外,大多数网站功能都可以。

websocket 以某种方式无法连接,如浏览器的错误所示:

WebSocket connection to 'ws://myproject.com/ws/chat/ADVPKG/' failed: Error during WebSocket handshake: Unexpected response code: 500 

查看服务器的错误日志,我看到:

2022/01/06 08:13:02 [alert] 16624#16624: *8421 768 worker_connections are not enough while connecting to upstream, client: 127.0.0.1, server: www.myproject.com, request: "GET /ws/chat/ADVPKG/ HTTP/1.1", upstream: "http://127.0.0.1:80/ws/chat/ADVPKG/", host: "myproject.com"

下面是我的代码: asgi.py

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'

import django
django.setup()

from django.core.asgi import get_asgi_application
django_asgi_app = get_asgi_application()


from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing

application = ProtocolTypeRouter({
  "http": django_asgi_app,
  "websocket": AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name www.myproject.com
                myproject.com
                ""
                1X.XXX.XX.XXX
                ;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/ubuntu/stochie;
    }

    location /ws/ {
        proxy_pass http://0.0.0.0;
        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 / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

基本上:

  1. 我很确定问题出在 nginx 配置上,因为没有 nginx,每个功能都能完美运行
  2. 我严重怀疑 'proxy_pass http://0.0.0.0;' 可能是错误的,根据一份论坛问卷,这是由于代理传递点指向自身的无限循环。到目前为止,根据其他论坛问卷,我尝试了 'localhost'、'localhost:8000'、http://django、http://uvicorn 但无法解决问题。

我觉得是你的问题asgi.py

从您的 asgi.py 中删除路由并将此代码放入您的 asgi.py

import os
import django
from channels.routing import get_default_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

django.setup()
application = get_default_application()

然后在下面创建 routings.py 类似的内容,并将 myproject.routings.application 放入您的 settings.py

application = ProtocolTypeRouter({
    'websocket': OriginValidator(
        TokenAuthMiddleware(
            URLRouter([
                url(r"^ws/courier/$", CourierConsumer.as_asgi()),
                url(r"^.*$", NoRouteFoundConsumer.as_asgi()),
            ])
        ),
        ['*'],
    ),
})