Websockets не работают с каналами Django после развертывания
Я пытаюсь развернуть свой проект Django, но столкнулся с некоторыми трудностями.
Все прекрасно работает на локальной машине.
Я использую Django + nginx + uvicorn (запущенный супервизором). Также, я получил свой SSL сертификат в использовании.
Когда я пытаюсь подключиться к websocket (/ws) через загрузку страницы и заставить мои js файлы работать, я получаю сообщение в консоли:
WebSocket connection to 'wss://example.com/ws/' failed
Вот моя конфигурация nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
server_name example.com;
client_max_body_size 100M;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
location /ws/ {
proxy_pass https://uvicorn/ws;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_intercept_errors on;
proxy_redirect off;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
}
location /static/ {
root /root/server/social;
expires 1d;
}
location /media/ {
root /root/server/social;
expires 1d;
}
location / {
proxy_pass https://uvicorn;
proxy_set_header Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
upstream uvicorn {
server unix:/tmp/uvicorn.sock;
}
И конфигурация супервизора
[program:django]
command = /root/server/social/venv/bin/python -m uvicorn myproject.asgi:application --uds /tmp/uvicorn.sock --ssl-keyfile=/etc/letsencrypt/live/mysite.com/privkey.pem --ssl-certfile=/etc/letsencrypt/live/mysite.com/fullchain.pem
directory = /root/server/social
stderr_logfile=/var/log/long.err.log
stdout_logfile=/var/log/long.out.log
autostart=true
autorestart=true
Когда все готово, я запускаю nginx: service nginx restart. Я не получаю никаких ошибок.
После этого я запускаю service supervisor restart. И вот в чем дело. Если никто не использует сайт, в моих логах (/var/log/long.err.log) я не получаю ошибок:
INFO: connection closed
INFO: Shutting down
INFO: Finished server process [606]
INFO: Started server process [660]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: Uvicorn running on unix socket /tmp/uvicorn.sock (Press CTRL+C to quit)
Но если кто-то использует веб-сайт и активирует websocket, я получаю:
File "/root/server/social/venv/lib/python3.9/site-packages/websockets/legacy/protocol.py", line 1216, in write_close_frame
await self.write_frame(True, OP_CLOSE, data, _state=State.CLOSING)
File "/root/server/social/venv/lib/python3.9/site-packages/websockets/legacy/protocol.py", line 1189, in write_frame
await self.drain()
File "/root/server/social/venv/lib/python3.9/site-packages/websockets/legacy/protocol.py", line 1178, in drain
await self.ensure_open()
File "/root/server/social/venv/lib/python3.9/site-packages/websockets/legacy/protocol.py", line 921, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: sent 1000 (OK); no close frame received
INFO: connection closed
Вот все, что связано с websockets в структуре проекта, если нужно:
routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r"ws/messenger/", consumers.ChatConsumer.as_asgi()),
re_path(r"ws/profile/", consumers.ProfileConsumer.as_asgi()),
re_path(r"ws/like/", consumers.LikeConsumer.as_asgi())
]
asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import messenger.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = ProtocolTypeRouter({
"http":get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(messenger.routing.websocket_urlpatterns)
)
})
consumers.py
import json
from channels.generic.websocket import WebsocketConsumer
from profile.models import User, Message, Chat, Publication
from asgiref.sync import async_to_sync
from datetime import datetime
group_members = []
class ChatConsumer(WebsocketConsumer):
...
class ProfileConsumer(WebsocketConsumer):
...
class LikeConsumer(WebsocketConsumer):
...
Я могу предоставить больше информации, если это необходимо. Надеюсь, ваш отзыв поможет мне!