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

Django Channels中WebSocket无法接收客户端消息,需实现消息接收与30秒实时更新并行的问题排查

Django Channels中WebSocket无法接收客户端消息,需实现消息接收与30秒实时更新并行的问题排查

我帮你梳理下问题的核心原因,以及对应的解决方案:

1. 最关键的阻塞问题:无限循环协程卡住了Consumer事件循环

你的connect方法最后调用了await self.updateDataIfChanged(),而这个方法里是无限while循环。await会等待整个协程执行完成,但这个循环永远不会结束,导致Consumer的事件线程被完全阻塞——连receive方法都没机会被调用,自然接收不到客户端发来的消息。

解决方案:用asyncio.create_task启动后台定时任务

把阻塞的await改成异步任务形式,让定时更新逻辑在后台并行运行,不占用主协程的处理资源:

首先在文件顶部导入asyncio:

import asyncio
from asyncio import sleep
from channels.generic.websocket import AsyncWebsocketConsumer
# ... 其他导入代码

然后修改connect方法的最后一行:

async def connect(self):
    await self.accept()

    self._allmeasurements = DatasetBuilder(1)

    self._date_end: datetime = datetime.now(timezone(timedelta(hours=+1)))
    self._date_start: datetime = self._date_end - timedelta(minutes=15)
    self._dataset = self._allmeasurements.get_relevant_messages(self._date_start, self._date_end)
    self._hash_dataset = hash(str(self._dataset))
    await self.send(str(self._dataset))

    # 用create_task启动后台任务,不阻塞主协程
    asyncio.create_task(self.updateDataIfChanged())

另外注意你updateDataIfChanged方法里的缩进错误(if代码块未缩进),修正后代码如下:

async def updateDataIfChanged(self):
    while True:
        self.updateDate()  # 确保这个方法已正确实现,用于更新日期范围
        self._dataset = self._allmeasurements.get_relevant_messages(self._date_start, self._date_end)
        if self._hash_dataset != hash(str(self._dataset)):
            await self.send(str(self._dataset))
            self._hash_dataset = hash(str(self._dataset))
        await sleep(30)
        print("30s passed.")

2. 客户端发送时机问题:确保连接建立后再发消息

你的前端代码直接调用socket.send,但WebSocket连接是异步建立的,如果在连接完成前发送消息,消息可能会丢失(虽然try/catch没报错,但实际没发送到服务器)。

解决方案:把发送逻辑放在onopen回调里

const socket = new WebSocket('ws://localhost:8000/ws/draw_chart/');

socket.onopen = function(event) {
    console.log("WebSocket连接已建立,开始发送消息...");
    try {
        socket.send("DO YOU HEAR ME!?");
    } catch (error) {
        console.error("发送消息到WebSocket时出错:", error)
    }
};

// 可选:监听服务器返回的消息,验证通信是否正常
socket.onmessage = function(event) {
    console.log("收到服务器消息:", event.data);
};

3. 其他需要确认的细节

  • 确保Redis服务正常运行:你的CHANNEL_LAYERS配置依赖Redis,要确认WSL中的Redis已经启动,且本地能访问6379端口。
  • 检查updateDate方法:你的代码中调用了这个方法但未给出实现,要确保它能正确更新self._date_start和self._date_end,否则定时更新的时间范围可能不符合预期。

修改完这些后,你的Consumer就能同时处理客户端消息接收和30秒定时更新任务——后台任务在事件循环中并行运行,主协程可以随时响应receive事件。

备注:内容来源于stack exchange,提问作者MHF

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 18:14:37