解决asgiref版本超过3.2+时连接guacamole报Application instance took too long to shut down and was killed问题

本人出现该问题的情况:

软件包版本:channels==4.1.0,django==4.2,asgiref==3.8.1(下载Django时默认依赖下载的,也是该问题的部分原因),pyguacamole==0.11,

触发场景:使用channels的异步连接类AsyncWebsocketConsumer做websocket,在代码内部去连接远程guacd服务并与之进行交互式时出现。然后页面去链接这个websocket时并不会立马报错但页面无法输入任何内容,大概几分钟后查看websocket日志出现此错误。

问题原因:

在使用asgiref版本较高时,使用async定义的函数在内容去创建非异步的socket客户端时,(类似这种,self.client.receive函数就是去调用pyguacamole的发送方法去给guancd服务发送信息的,而pyguacamole是在内部其他函数里面创建的与guancd服务连接的客户端)

会出现异步函数与socket客户端交互问题。而出现这个错误的原因是pyguacamole包的内容就是创建了非异步的socket客户端(如下这张就是pyguacamole创建的与远程guacd服务连接的客户端函数)

而最终导致这个错误的主要原因是,使用async创建的协程没有被正确释放掉,超时后被杀死了。

至于为什么使用async声明的异步函数与非异步的socket客户端交互有问题且没有被正确释放掉,有待深入了解,在此不过多赘述,希望知道的网友能给出答案。

如何解决!

两种办法:

一、手动重装asgiref的版本

将asgiref的版本降到3.2.10,这种办法也是我在很多地方看到的并且也是最方便的.

pip install asgiref==3.2.10 -i https://mirrors.aliyun.com/pypi/simple/

不过这么做是有后果的,那就是你的Django不能超过4.0且包喊4.0。如果你不信想尝试一下,那么你就会惊喜的看到这个错误,如果你得项目不需要升级的那么高的版本那当我没说。但是这就意味着Django4.x与你无缘了~

packages/django/core/handlers/asgi.py", line 6, in <module>
    from asgiref.sync import ThreadSensitiveContext, sync_to_async
ImportError: cannot import name 'ThreadSensitiveContext' from 'asgiref.sync' (/home/wqzb-dev/venv/lib/python3.9/site-packages/asgiref/sync.py)

好,接下啦是鄙人耗时两天做出来的,可以说是全网唯一了(吹牛的别相信哈哈哈哈哈)

二、卸载pyguacamole,然后手撸一个支持异步的pyguacamole

既然pyguacamole他不支持异步,Djanog4.x也来凑热闹,那就打。当时也是找遍了全网没找到解决办法,索性就直接去github把pyguacamole的源码下下来自己给他重写一下。当时的想法就是既然他不支持异步,那就给他写成支持异步的。

核心思路很简单就是把pyguacamole内部连接guacd创建socket客户端的那个方法换成异步创建socket客户端就可以了。是不是超级简单。

从这个👇

变成这个👇

既然都把异步都做到这了,那就做到底吧,然后我就吧整个guacamole包里面的函数变成异步的了,如果你想直接使用我改好的可自行去github拉取(pythonxiaocaiji/asguacd: 在pyguacamole的基础上做了兼容异步,并将其修改为异步执行,解决了asgiref==3.2以后与非异步socket客户端通信问题 (github.com)

使用方法和原来的pyguacamole大同小异

# async异步函数里面的参考使用方式
from guacamole.client import AsyncGuacamoleClient

client = AsyncGuacamoleClient('127.0.0.1', 4822)
# 创建连接
await client.handshake(protocol='rdp', hostname='localhost', port=3389)
# 读取guacd服务返回的信息
await  client.receive()
# 给guacd服务发送i信息
await  client.send(instruction)

如果你不想在async异步函数里面使用修改为异步的pyguacamole包,那么恭喜你又打开了新世界的大门,这种方式我没测试过,不过我相信有这个想法的你,你一定可以做到的。如果你做到了请分享给我~哈哈哈哈哈哈

如果文中有问题请随时指出,或你使用鄙人修改后的pyguacamole有问题也请第一时间来批评我哈哈哈哈

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值