本人出现该问题的情况:
软件包版本: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有问题也请第一时间来批评我哈哈哈哈