django频道页面在加载时卡住

frebpwbc  于 2021-06-09  发布在  Redis
关注(0)|答案(1)|浏览(555)

我创建了一个简单的django通道消费者,它连接到redis通道并从这个通道接收一些数据,我想把这些数据发送到前端。
消费者能够连接到消费者并接收数据;问题是,如果我在消费者运行时尝试加载页面,页面将在加载时被卡住。我确信这是因为redis通道的连接是一个阻塞操作,或者线程有问题。我对这个概念还不熟悉,所以我决定提出一个问题。
这是我的消费者:

  1. class EchoConsumer(AsyncConsumer):
  2. async def websocket_connect(self, event):
  3. self.send({
  4. 'type': 'websocket.accept'
  5. })
  6. self.receive(event)
  7. def receive(self, event):
  8. redis_url = 'redis://localhost:6379/0'
  9. connection = redis.StrictRedis.from_url(redis_url, decode_responses=True)
  10. channel = 'TEST'
  11. params = urllib.parse.parse_qs(self.scope.get('query_string', b'').decode('utf-8'))
  12. pubsub = connection.pubsub(ignore_subscribe_messages=True)
  13. pubsub.subscribe(channel)
  14. for message in pubsub.listen():
  15. # self.send({
  16. # 'type': 'websocket.send',
  17. # 'text': message['data'],
  18. # })
  19. print(message['data'])
  20. async def websocket_disconnect(self, event):
  21. print('DISCONNECTED!')

所以发生的事情是,我可以看到数据被打印到我的控制台,但如果我试图离开该页面,到达我的网站的另一个部分,该页面将在加载时卡住。有人能帮我修一下吗?

gt0wga4j

gt0wga4j1#

这里有两件事你可以试着去做。

订阅一次并将此信息发送到所有打开的连接

你现在的问题是 pubsub.listen(): 将永远循环(永不停止)。因此,您的消费者将永远无法继续处理更多的消息。
因为(至少在本例中)看起来您总是使用静态值(不依赖于用户的请求)来访问redis,所以您最好在您的消费者之外进行此订阅(在django命令中https://docs.djangoproject.com/en/3.0/howto/custom-management-commands/)
然后您可以使用该命令,然后通过通道层将这些消息发送给订阅的消费者。
这会让你的消费者看起来像这样

  1. class EchoConsumer(AsyncJsonWebsocketConsumer):
  2. async def on_message(self, message):
  3. await self.send_json(message)

然后在管理命令instread of printing中,您可以使用

  1. async_to_sync(channel_layer.group_send)(
  2. "echo_group",
  3. {"type": "on.message", "rate":Rate, "quantity": Quantity, "symbol": Symbol, "order": Order},
  4. )

为每个打开的连接订阅一次

只有当您希望每个websocket连接的订阅不同时,才应该这样做(例如,您正在url/query/headers中使用一个值,或者仅当用户使用给定的筛选器值向您的消费者发送ws-message时才订阅。
做这件事是一件困难的事 LOT 更复杂的原因有:
redis不会像处理websocket连接那样处理到它的大量打开的连接。
您需要设置一个嵌套的异步任务,该任务可以处理来自redis的事件,这样它们就不会阻塞其他使用者。
如果你仍然需要这个功能,我很乐意用一个解决方案更新答案(但警告它会很长)。

展开查看全部

相关问题