django - 通道:为什么在处理结束时发送消息
问题描述
为什么使用同步功能get_channel_layer().send()
,消息在处理结束时发送
def external_send(channel_name, data):
channel_layer = get_channel_layer()
send_sync = async_to_sync(channel_layer.send)
send_sync(
channel_name,
{
"type": "send_json",
"message": {"datetime": datetime.datetime.now().isoformat(), **data},
},
)
self.send()
按预期在消费者工作中使用
这是我用于测试目的的消费者类:
class TestConsumer(JsonWebsocketConsumer):
def connect(self):
self.accept()
def disconnect(self, close_code):
pass
def receive_json(self, content, **kwargs):
logger.debug(f"RECEIVE {content}")
self.send_json(
{
"id": 1,
"text": "Before sleep: self.send_json",
"datetime": datetime.datetime.now().isoformat(),
}
)
external_send(
self.channel_name, {"id": 2, "text": "Before sleep external_send"}
)
sleep(10) # Simuleting long processing
self.send_json(
{
"id": 3,
"text": "After sleep: self.send_json",
"datetime": datetime.datetime.now().isoformat(),
}
)
super().receive_json(content, **kwargs)
logger.debug("END")
在前端我收到订单
- {id:1,文本:“睡前:self.send_json”,日期时间:“2020-05-29T14:30:58.226545”}
- {id:3,文本:“睡眠后:self.send_json”,日期时间:“2020-05-29T14:31:03.244865”}
- {id:2,文本:“睡前 external_send”,日期时间:“2020-05-29T14:30:58.230164”}
解决方案
作为回答,每个渠道消费者都有自己的小运行循环。它一次只处理一个事件。这个单一的运行循环用于从客户端(通过 ws)接收的消息和通过通道层上的组发送事件处理的消息。
如果你receive_json
的方法你正在睡觉,那就是在睡觉循环,所以不会发生其他任何事情。receive_json
需要在处理通过通道层发送的任何消息之前完成。
查看您的代码,还有其他几点需要指出
同步sleep
如果您确实需要sleep
在一个方法中永远不要在同步方法中这样做,这将使您的整个python 程序休眠(一切都会休眠)。
使用异步消费者然后你就可以await asyncio.sleep(20)
了,然后sleep
你的单个消费者的运行循环和其他 websocket 连接等将继续运行。对于任何其他长时间运行的任务也是如此,您应该使用异步使用者,然后对await
这些长时间运行的任务使用异步线程池。
您不应尝试send_json
直接将组发送到该方法。
Intread 你应该在你的消费者上创建一个方法,handle_message
这个方法可以调用send_json
并且你的组发送应该发送带有 type 的消息handle.message
。
推荐阅读
- php - Laravel Cashier + 你能自定义订阅的附加字段吗
- java - 在spring项目中添加方面后出现UnsatisfiedDependencyException
- go - 从 Golang 中的 Cloud Function trigger ref create 获取实时数据库 nodeID
- linux - 'sudo -su' 到底是什么?
- python - 为什么两个numpy(n,)向量的矩阵@乘积是点积,而不是外积?
- cloud-foundry - Cloudfoundry VCAP_SERVICES 变量未提供给 django 容器
- reactjs - 如何使用 Reactjs 从列表中删除元素
- unit-testing - 如何在不知道 Go 中显式类型的情况下从接口创建新对象?
- bash - 如何将分层数据回显到bash中的文件中
- java - H2 DB 特殊字符排序不正确