我做了一个目标检测的程序,
前端核心代码如下:
var ws = new WebSocket(websocket_url);
ws.onmessage = function (evt)
{ // 处理逻辑 }
https://github.com/django/channels/issues/1981
比较迷惑,而且异常全都是 autobahn.exception.Disconnected
在consumer 中的code 如下:
try:
await super().send(json_text_data)
except autobahn.exception.Disconnected:
await self.disconnect()
await self.close()
使用的是django channel 4.0 ,发现如果是只用self.close() 是下面的报错,一段时间后还要清除 channel_layer 中的东西应该是
Application instance <Task pending name='Task-2388' coro=<ASGIStaticFilesHandler.__call__() running at C:\Users\wyaning.conda\envs\qalab\lib\site-packages\django\contrib\staticfiles\handlers.py:101> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x0000027CDCB1B5B0>()]>> for connection <WebSocketProtocol client=['10.167.118.211', 58719] path=b'/ws/ObjectDetection/ObjectDetection0/'> took too long to shut down and was killed.
如果是先用disconnect 那么就是程序发送端也就断了,需要10秒左右重新建立链接,很头大。
报错如下:
https://github.com/django/channels/issues/1119
disconnect 和 close 的文档怎么描述两个接口的。
127.0.0.1:40148 - - [23/Sep/2021:18:58:18] "WSCONNECTING /operation/api/ws/smart_station/car_real_time/609a646968206d11a655d3e3/" - -
127.0.0.1:40148 - - [23/Sep/2021:18:58:18] "WSCONNECT /operation/api/ws/smart_station/car_real_time/609a646968206d11a655d3e3/" - -
==== 连接成功
==== 连接成功, 并且来到了最后一行
127.0.0.1:40148 - - [23/Sep/2021:18:58:19] "WSDISCONNECT /operation/api/ws/smart_station/car_real_time/609a646968206d11a655d3e3/" - -
127.0.0.1:36798 - - [23/Sep/2021:19:01:41] "WSCONNECTING /operation/api/ws/smart_station/car_real_time/609a646968206d11a655d3e3/" - -
从上述的日志中发现,我自己打印的连接上之后的日志全部打印出来了,并且整个连接也成功连上了,但是很快就立刻断开了。并且断开的时候并没有调用我的consumer中的disconnect方法,相应的日志也没有打印出来。
排查修改
排查修改过的代码,发现redis配置发生过变更,换了新的redis实例。与运维同学沟通,发现新的redis的版本为4.0,而原先的redis是5.0版本
作者:Jayce_xi
链接:http://events.jianshu.io/p/c2d31862901d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Django Channels是一个基于Django的WebSockets和HTTP长轮询应用程序框架。如果你的Django Channels应用程序在一段时间后自动断开,可能有以下几个原因:
超时:默认情况下,Django Channels的WebSocket连接和HTTP长轮询连接都有一个超时时间。如果在规定时间内没有收到任何消息,连接将被关闭。可以通过在settings.py中设置CHANNELS_WS_KEEPALIVE和CHANNELS_WS_TIMEOUT来延长超时时间。
内存泄漏:如果你的应用程序中存在内存泄漏,可能会导致连接自动断开。可以使用内存分析工具来检测内存泄漏,并尝试修复它们。
代理:如果你的应用程序在代理后面运行,可能会导致连接自动断开。在这种情况下,你可能需要配置代理以正确处理WebSocket和HTTP长轮询连接。
负载均衡:如果你的应用程序在负载均衡器后面运行,可能会导致连接自动断开。在这种情况下,你可能需要配置负载均衡器以正确处理WebSocket和HTTP长轮询连接。
为了解决这个问题,你可以尝试以下几个步骤:
延长超时时间:在settings.py中设置CHANNELS_WS_KEEPALIVE和CHANNELS_WS_TIMEOUT来延长超时时间,以确保连接不会因为超时而自动断开。
检测内存泄漏:使用内存分析工具来检测内存泄漏,并尝试修复它们。
配置代理和负载均衡器:如果你的应用程序在代理或负载均衡器后面运行,需要配置它们以正确处理WebSocket和HTTP长轮询连接。
调整连接池:如果你使用的是Channels内置的连接池,可以尝试调整连接池的大小或其他参数,以确保连接池中始终有足够的连接可用。
总之,如果你的Django Channels应用程序在一段时间后自动断开,需要仔细检查可能的原因,并尝试进行相应的调整和修复。
该回答引用GPTᴼᴾᴱᴺᴬᴵ
这个问题可能是由于WebSocket连接在一段时间内没有活动而被服务器断开导致的。根据异常信息来看,autobahn.exception.Disconnected表示WebSocket连接已断开。
-
为了解决这个问题,可以考虑在代码中增加一些措施来保持WebSocket连接的活跃性,以避免连接因为长时间没有活动而被服务器断开。
-
一种常见的方法是定期向客户端发送一些数据,以保持连接的活跃性。可以在consumer中添加一个定时器,每隔一段时间向客户端发送一个空的消息,以确保WebSocket连接仍然处于活动状态。例如:
import asyncio
from channels.consumer import AsyncWebsocketConsumer
class MyConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.accept()
# 在连接成功后,启动定时器,每隔30秒发送一个空消息
self.send_heartbeat()
async def send_heartbeat(self):
while self.websocket.connected:
try:
await self.send("")
await asyncio.sleep(30)
except:
# 连接已断开
break
async def receive(self, text_data=None, bytes_data=None):
# 处理接收到的消息
pass
async def disconnect(self, code):
# 关闭连接
pass
总之,要解决这个问题,关键是要保持WebSocket连接的活跃性,避免连接因为长时间没有活动而被服务器断开。定期发送心跳消息或者启用WebSocket的keepalive选项都是有效的方法。
不知道你这个问题是否已经解决, 如果还没有解决的话: