必须用ASGI服务器(如daphne或uvicorn)启动,而非runserver;确认ASGI_APPLICATION指向正确asgi.py,其中含ProtocolTypeRouter,且前端URL协议为ws://或wss://。

WebSocket连接一直断开,ASGI_APPLICATION 配置对了吗?
Django Channels 要跑 WebSocket,必须用 ASGI 服务器(如 daphne 或 uvicorn),而不是默认的 WSGI(runserver 或 gunicorn)。常见错误是只改了 settings.py 里的 ASGI_APPLICATION,却仍用 python manage.py runserver 启动——这根本不会走 ASGI 路由,WebSocket 握手直接 404 或被拒绝。
必须确认三点:
-
ASGI_APPLICATION = "myproject.asgi.application"指向的是项目根目录下的asgi.py文件,且该文件里已正确导入ProtocolTypeRouter和URLRouter - 启动命令换成:
daphne myproject.asgi:application -b 0.0.0.0:8000(或uvicorn myproject.asgi:application --host 0.0.0.0 --port 8000) - 前端建立连接时,URL 协议必须是
ws://(开发环境)或wss://(生产),不能写成http://
consumers.py 里用 AsyncWebsocketConsumer 还是 SyncWebsocketConsumer?
绝大多数场景该用 AsyncWebsocketConsumer。Django Channels 的异步消费者是为高并发设计的,同步消费者会在每个连接上占一个线程,容易在连接数上升后卡死或耗尽线程池。
但注意:如果你在 consumer 中调用了 Django ORM 查询(比如 User.objects.get()),不能直接写,会阻塞事件循环。必须用 database_sync_to_async 包裹:
立即学习“Python免费学习笔记(深入)”;
from channels.db import database_sync_to_async
from django.contrib.auth.models import User
@database_sync_to_async
def get_user_by_id(user_id):
return User.objects.get(id=user_id)
否则你会看到 SynchronousOnlyOperation 错误,或者连接莫名关闭。
如何让多个客户端收到同一消息?别只用 self.send()
self.send() 只发给当前连接的客户端,实现广播得靠 Channel Layer。Channels 默认使用 Redis 作为背板(channels-redis),必须先装好并配置 CHANNEL_LAYERS:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)],
},
},
}
然后在 consumer 中用 channel_layer.group_send():
- 加入组:
await self.channel_layer.group_add("chat_room", self.channel_name) - 发广播:
await self.channel_layer.group_send("chat_room", {"type": "chat.message", "message": "hello"}) - 接收广播需定义对应方法:
async def chat_message(self, event): await self.send(text_data=event["message"])
漏掉 group_add 或没实现 chat_message 方法,消息就石沉大海。
生产部署时 WebSocket 连接超时,Nginx 配置漏了哪几行?
Nginx 默认会关闭空闲长连接,WebSocket 必须显式开启升级支持。缺任意一行都会导致连接几秒后断开:
location /ws/ {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
其中 proxy_http_version 1.1 和两个 proxy_set_header 是关键。如果用的是 uvicorn,还要确保它启用了 --timeout-keep-alive(默认 5 秒太短,建议设为 60+)。
Redis 连接池、SSL 终止位置、跨域头(Access-Control-Allow-Origin)这些点,线上一出问题就很难定位——它们不报错,只静默丢连接。


















