如何设计扭曲的工厂来处理断开连接?

时间:2011-03-27 03:33:34

标签: python twisted

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

以下是我所拥有的一个简短示例:

Factory(protocol.ReconnectingClientFactory):

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

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

我认为最好是在出现连接问题时通知顶级脚本(导入模块的脚本)。这样,顶级脚本可以定义断开连接解析行为,而不是在模块中对其进行硬编码。但是,将连接问题传达给顶级脚本的最佳方法是什么?

我可以提出异常,但它会被捕获到哪里?我想反应堆会抓住它,但这有什么帮助呢?

我无法触发回调或错误,以通知顶级脚本连接问题。

顶级脚本可以提供在发生连接问题时要调用的特定函数[作为参数]。这是一个好的设计吗?

1 个答案:

答案 0 :(得分:3)

这个问题有点过于抽象,无法提供直接的答案。这取决于您的顶级模块正在做什么。

但是,您应该考虑使用endpoints,而不是ClientFactory。这可能会解决您的一些设计问题。接收连接丢失通知是一个小问题(因为ClientFactory.clientConnectionLost实际上是IProtocol.connectionLost的重复通知,它在端点API中不再存在;所以如果你必须包装IProtocol对象关心这一点)但它确实让你使用更通用的机制来重试失败的连接,而不是clientConnectionFailed而不是Deferred你得到的错误来自connect。因此,举例来说,如果你想做的就是“在你成功之前保持重新连接”,你可以使用这个完全通用的Deferred - 重试循环,而不是像ReconnectingClientFactory这样的连接特有的东西:

# 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)

同样,如果你可以使deferredThing函数返回Deferred,只有当你的协议的应用程序逻辑完成时才会触发它,除了调用IStreamServerEndpoint.connect之外,还要注意{{1}如果在有趣的逻辑完成之前连接丢失,则会失败。

connectionLost可以是在系统的多个级别上管理此类异步重试状态的有效方法。