2011-03-27 114 views
5

我在模块中有一个ReconnectingClientFactory。我希望模块尽可能灵活。我只需要一个单独的TCP连接。我使用工厂作为此连接的持续接口。在过去,工厂会通过无休止地重试连接来响应断开连接,而不会通知顶级脚本(导入模块的脚本)存在连接问题。如何设计扭曲的工厂来处理断开连接?

这里是什么,我有一个简单的例子:

Factory(protocol.ReconnectingClientFactory): 

    def clientConnectionFailed(self, connector, reason): 
     ... 

    def clientConnectionLost(self, connector, reason): 
     ... 

我认为这是最好的,如果我告诉了顶级脚本(即导入模块脚本)时存在连接问题。通过这种方式,顶层脚本可以定义断开连接解析行为,而不是全部在模块中进行硬编码。但是,将连接问题传达给顶层脚本的最佳方式是什么?

我可以举一个例外,但它会被捕获到什么地方?我想反应堆会抓住它,但这有什么帮助?

没有回调或errbacks我可以通知顶部脚本的连接问题。

顶部脚本可以提供特定的函数[作为参数]在连接问题发生时被调用。这是不错的设计吗?

回答

3

这个问题有点太抽象,不能提供直接的答案。这取决于你的顶级模块在做什么。

但是,您应该考虑使用endpoints而不是ClientFactory。这可能解决您的一些设计问题。接收连接丢失通知是一个小窍门(因为ClientFactory.clientConnectionLost实际上是IProtocol.connectionLost的重复通知,因此它不再存在于端点API中;因此,如果您关心该对象,则必须包装IProtocol对象),但它确实允许您使用更通用的重试的机制失败连接,而不是clientConnectionFailed,您只需从connect得到Deferred errback。同样

# Warning, untested, sorry if it's broken. 
@inlineCallbacks 
def retry(deferredThing, delay=30.0, retryCount=5): 
    retries = retryCount 
    while True: 
     try: 
      result = yield deferredThing() 
     except: 
      if not retries: 
       raise 
      retries -= 1 
      log.err() 
      yield deferLater(reactor, delay, lambda : None) 
     else: 
      returnValue(result) 

,如果:因此,举例来说,如果你想要做的是“保持重新连接,直到你成功”的所有,你可以使用这个完全通用Deferred -retry环,而不是特定的连接类似ReconnectingClientFactory您可以使deferredThing函数返回Deferred,该函数仅在协议的应用程序逻辑完成时才会触发,此外还调用IStreamServerEndpoint.connect,观察connectionLost,并且如果在有趣的逻辑完成之前连接已丢失,则会失败。

Deferreds可以成为跨系统多级管理这种异步重试状态的有效方法。

+1

这似乎是一个不完整的解决方案,因为它只提供了一种方式来处理失败的连接尝试,而不是丢失的连接。如何在没有协议协议的情况下处理丢失的连接? – 2011-03-27 13:44:54