Django Channels AsyncWebSocketConsumer遇1005连接关闭及RuntimeError问题求助
解决方案
解决 ConnectionClosedError
该错误是客户端已断开连接,但服务端仍尝试发送心跳响应导致的。修改receive方法,在发送前检查连接状态,同时针对性捕获异常:
async def receive(self, text_data): try: if text_data == "healthcheck": # 检查WebSocket连接是否仍活跃 if not self.scope.get('websocket', {}).closed: await self.send( text_data=json.dumps({"type": "healthcheck", "data": self.group_name}) ) else: logger.info(f"Unsupported WS Event: {text_data}") except ConnectionClosedError: logger.warning("尝试向已关闭的连接发送心跳响应") except Exception: logger.exception("处理客户端消息失败")
解决 RuntimeError: Unexpected ASGI message 'websocket.send'
这个错误出现在连接关闭后,服务端仍有异步任务尝试发送消息。需要在断开时清理所有可能的发送任务,同时封装安全发送逻辑:
1. 封装安全发送方法
在Consumer类中添加统一的安全发送方法,避免向已关闭连接发消息:
async def safe_send(self, text_data): try: if not self.scope.get('websocket', {}).closed: await self.send(text_data=text_data) except ConnectionClosedError: logger.warning("安全发送失败:连接已关闭")
之后在receive中替换原send调用:
await self.safe_send(json.dumps({"type": "healthcheck", "data": self.group_name}))
2. 断开时清理异步任务
如果Consumer中有定时心跳等异步任务,需在disconnect中取消任务:
class YourConsumer(AsyncWebSocketConsumer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.healthcheck_task = None async def connect(self): # 原有连接逻辑... # 若有定时心跳任务,启动并保存句柄 self.healthcheck_task = asyncio.create_task(self.send_periodic_healthcheck()) async def disconnect(self, close_code): try: # 取消定时心跳任务 if self.healthcheck_task: self.healthcheck_task.cancel() try: await self.healthcheck_task except asyncio.CancelledError: pass # 离开组 await self.channel_layer.group_discard(self.group_name, self.channel_name) await self.log_request("disconnect") except Exception: logger.exception("用户断开Socket连接失败")
额外注意事项
- 避免使用裸
except,捕获特定异常更便于定位问题 - 确认
group_discard的参数self.group_name、self.channel_name在断开时有效 - 检查客户端逻辑,避免连接断开后仍发送心跳请求
内容的提问来源于stack exchange,提问作者BillPull
相关产品推荐
相关产品推荐

