2011-03-27 151 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