Python 当Pyro4客户端意外断开连接时释放资源
我有一个Pyro4分布式系统,多个客户端连接到一台服务器。这些客户端连接到一个远程对象,该对象可能会在系统中分配一些资源(在我的例子中是虚拟设备) 一旦客户端断开连接(比方说因为崩溃),我需要释放这些资源。检测特定客户端与特定对象断开连接的正确方法是什么? 我试过不同的方法:Python 当Pyro4客户端意外断开连接时释放资源,python,pyro4,Python,Pyro4,我有一个Pyro4分布式系统,多个客户端连接到一台服务器。这些客户端连接到一个远程对象,该对象可能会在系统中分配一些资源(在我的例子中是虚拟设备) 一旦客户端断开连接(比方说因为崩溃),我需要释放这些资源。检测特定客户端与特定对象断开连接的正确方法是什么? 我试过不同的方法: 重写守护进程.clientDisconnected方法。我从这个方法中得到一个连接参数。但我无法将其与对象关联,因为我无法访问该连接所指的远程对象 使用Daemon.clientDisconnected中的Pyro4.c
- 重写
方法。我从这个方法中得到一个守护进程.clientDisconnected
参数。但我无法将其与对象关联,因为我无法访问该连接所指的远程对象连接
- 使用
中的Daemon.clientDisconnected
。这不起作用,因为它是线程本地对象。如果我的池中连接的客户端比线程多,就会得到重复的上下文Pyro4.current\u context
- 使用Pyro4项目提供的“usersession”示例中的
对我没有帮助,因为我再次从Proxy.\u pyroAnnotations
属性获取注释,该属性在调用Pyro4.core.current\u context.annotations
时显示错误的注释(我想是由于线程相关的问题)守护进程.clientDisconnected
- 在远程类中使用
和instance\u mode=“session”
方法(因为每个客户端都有一个单独的类实例,所以一旦客户端断开连接,该实例就应该被销毁)但是这依赖于\uuuu del\uuuu
方法,正如一些Python程序员所指出的那样,该方法存在一些问题\uu del\uu
我添加了我当前的解决方案作为答案,但我真的很想知道是否有一种更优雅的方式来使用Pyro4,因为这种情况是网络编程中经常出现的模式。我使用
代理。_pyroHandshake
属性作为客户端的客户端ID,并覆盖守护进程。validateHandshake
和Daemon.clientDisconnected
。这样,在每个新连接上,我都会将握手数据(每个客户端都是唯一的)映射到一个连接。但我真的想知道在Pyro4中是否有一种优雅的方法来实现这一点,这是网络编程中经常出现的模式
请注意,客户端还可以扩展Pyro4.Proxy并使用_pyroAnnotations将客户端ID发送到所有远程调用,而不是将代理用作客户端的属性
class Client:
def __init__(self):
self._client_id = uuid.uuid4()
self._proxy = Pyro4.Proxy("PYRO:server@127.0.0.1")
self._proxy._pyroHandshake = self._client_id
self._proxy._pyroBind()
def allocate_resource(self, resource_name):
self._proxy.allocate_resource(self._client_id, resource_name)
class Server:
def __init__(self):
self._client_id_by_connection = {}
self._resources_by_client_id = {}
def client_connected(self, connection, client_id):
self._client_id_by_connection[client_id] = connection
self._resources_by_client_id[client_id] = []
def client_disconnected(self, connection):
client_id = self._client_id_by_connection[connection]
for resource in self._resources_by_client_id[client_id]
resource.free()
@Pyro4.expose
def allocate_resource(self, client_id, resource_name)
new_resource = Resource(resource_name)
self._resources_by_client_id[client_id].append(new_resource)
server = Server()
daemon.register(server, objectId="server")
daemon.clientDisconnect = server.client_disconnected
daemon.validateHandshake = server.client_connected
daemon.requestLoop()
Pyro 4.63可能会有一些内置的支持,以使其更容易实现。如果您从Github克隆当前的主机,您可以在此处阅读相关内容并尝试一下。也许您可以看看这是否会使您的用例更简单?关于
守护进程。clientDisconnected
:客户端可以访问多个对象通过其连接。因此,在这里不可能将任何内容与单个对象关联-客户端可以访问多个对象。这听起来是完美的解决方案。一旦得到一些结果,我将接受此答案。非常感谢。很高兴听到。请让我知道结果是否对您有效,以便我知道此解决方案是值得的我做了一些测试,Irmen。但是我最终发现了一些问题。不确定我是否误解了文档,或者它是否真的存在于库中。我在你的Github问题跟踪器中发布了测试场景。我在自己的系统中运行了测试。似乎是完美的解决方案。请注意最后的注释在文档部分。谢谢@Irmen。只是一个小小的提醒,Pyro 4.63现在已经发布,具有这个新功能。