You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:30:39