Search code examples
nginxgunicorndjango-channelsuvicornasgi

django channel issue during deployment


I am using Django Channels and deployed with NGINX+Gunicorn+Uvicorn and following the tutorial from Digital Ocean (i.e. https://www.digitalocean.com/community/tutorials/how-to-set-up-an-asgi-django-app-with-postgres-nginx-and-uvicorn-on-ubuntu-20-04)

I don't see any issue when I tried to run the site @ www.myproject.com:8000 without NGINX with the following command:

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

However, when I deployed with NGINX it is ok for most of the site functionality except the chat function page which employ django channels.

Somehow the websocket failed to connect through as shown by the error from browser:

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

Checking on the error log in the server, I saw:

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"

Included below is my code: 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;
    }
}

Basically:

  1. I am pretty sure the issue is the nginx configuration as without nginx every function work perfectly
  2. I heavily suspect that the 'proxy_pass http://0.0.0.0;' might be wrong which according to one forum questionnaire is due to infinite loop as proxy pass point to itself. So far based on other forum questionnaires, I have try 'localhost', 'localhost:8000', http://django, http://uvicorn but is not able to resolve the issue.

Solution

  • I think the problem is in you asgi.py

    remove the routings from your asgi.py and put this code in your 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()
    

    then create routings.py something like this below and put myproject.routings.application in your settings.py

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