首页 > 解决方案 > Django 频道错误“关闭时间太长并被杀死”。

问题描述

我在控制台日志中收到此错误,并且在提交表单时它不断加载不会将数据发布到服务器。

/home/Python/Working/Benutzerverwaltung/env/lib/python3.6/site-packages/channels/sessions.py:183>
wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at
0x7fab9fe51408>()]>> for connection <WebSocketProtocol
client=['127.0.0.1', 59462] path=b'/ws/stream/Sales'> took too long to
shut down and was killed.

这是我关闭频道的代码。

async def disconnect(self, code):
    async_to_sync(self.channel_layer.group_discard)(
        self.room_group_name,
        self.channel
    )
    await self.close()

async def websocket_disconnect(self, event):
    print("Disconnect", event)
    await self.send({
        "type": "websocket.close"
    })

如何解决这个问题?

标签: python-3.xdjangowebsocketdjango-channelsdjango-redis

解决方案


这个错误主要是因为协程挂起的时间比它应该的要长。

这个具体案例

在这种情况下,AsyncWebsocketConsumer.websocket_disconnect()被覆盖但没有调用super(),这意味着它StopConsumer()没有运行(参见channels/generic/websocket.py:228)。也许根本不要覆盖websocket_disconnect,因为这个例子中没有任何东西可以证明它是正确的。

另请注意,async_to_sync它适用于同步消费者,但这是一个异步消费者。而是使用:

await self.channel_layer.group_discard(
    self.room_group_name,
    self.channel
)

await self.close()不需要,因为断开连接已经发生。删除该行。

AsyncHttpConsumer

同样,AsyncHttpConsumer我经常犯的一个错误是调用await self.send_response(...)但之后忘记调用return,所以当你没想到时,函数会继续运行。

AsyncHttpConsumer还有一个关于未在handle(). 目前唯一的选择是添加额外的打印/记录行来确定什么正在运行/没有运行。

当心 django-debug-toolbar

另外值得注意的是,在你的异步消费者中添加debug-toolbar你的INSTALLED_APPS意愿会消除异常。请参阅此处的讨论。谨防!


推荐阅读