我最近使用pythonsocketio和aiohttp编写了一个客户机/服务器应用程序,我的应用程序基于异步名称空间(服务器端),此外,我的on\u消息事件中有许多等待调用,因此我必须使用异步锁来确保维护所需的流。为了实现这个行为,我编写了一个装饰器,并用它包装了每个关键的节类型函数。你知道吗
@async_synchronized('_async_mutex')
async def on_connect(self, sid, environ):
self._logger.info("client with sid: {} connected to namespace: {}!".format(
sid, __class__.__name__))
important_member = 1
await other_class.cool_coroutine()
important_member = 2
在我的构造函数中,我初始化了_async_mutex = asyncio.Lock()
装饰师:
def async_synchronized(tlockname):
"""A decorator to place an instance based lock around a method """
def _synched(func):
@wraps(func)
async def _synchronizer(self, *args, **kwargs):
tlock = self.__getattribute__(tlockname)
try:
async with tlock:
return await func(self, *args, **kwargs)
finally:
pass
return _synchronizer
return _synched
现在,在任何正常的用例中,一切都可以很好地工作(关闭/打开客户机会正确触发函数,锁也会按预期执行)。 需要注意的是,我的on\u disconnect函数是用完全相同的decorator和lock包装的。 我遇到的问题是,当客户端的网络适配器在物理上断开连接(正常的客户端关闭工作正常)时,我看到确实调用了on\u disconnect事件,但另一个共同例程当前持有锁。由于某些原因,事件被多次触发并最终陷入僵局。你知道吗
我已经用描述锁的状态/调用函数的打印来包装我的decorator,还为每个异步调用添加了try/catch。 似乎我的所有co例程都捕获了一个被取消的异常(我假定是由aiohttp执行的),因此一个“持有”锁的方法被取消,锁永远不会被释放。我试过用一个异步屏蔽()但行为没有改变。你知道吗
我在这里应该采用不同的异步锁方法吗?(移除锁可以完全解决问题,但可能会导致应用程序的计算部分出现未定义的行为)
更多代码示例: 实际的on\u connect和on\u disconnect事件:
@async_synchronized('_async_mutex')
async def on_connect(self, sid, environ):
self._logger.info("very good log message")
self._connected_clients_count += 1
@async_synchronized('_async_mutex')
async def on_disconnect(self, sid):
self._logger.info("very good disconnect message")
self._connected_clients_count -= 1
await self._another_namespace_class.inform_client_disconnect(sid) # this method is wrapped with the same decorator but with a different lock
注意:另一个没有连接到同一个客户端。另外,当发生网络断开连接时,我也看不到日志消息出现(我已将日志级别设置为debug)
目前没有回答
相关问题 更多 >
编程相关推荐