2010-10-14 46 views
7

我正在發出一個http請求。我在一個平臺上(android),網絡操作經常失敗,因爲網絡連接可能不會立即可用。因此,我想在完全失敗之前嘗試相同的連接N次。想到這樣的事情:重試一個http連接

DefaultHttpClient mHttp = ...; 

public HttpResponse runHttpRequest(HttpRequestBase httpRequest) 
    throws IOException 
{ 
    IOException last = null; 
    for (int attempt = 0; attempt < 3; attempt++) { 
     try { 
      HttpResponse response = mHttpClient.execute(httpRequest); 
      int statusCode = response.getStatusLine().getStatusCode(); 
      if (statusCode == 200) { 
       return response; 
      } 
     } catch (IOException e) { 
      httpRequest.abort(); 
      last = e; 
     } 
    } 

    throw last; 
} 

我最擔心的是連接處於某種狀態,在隨後的重試中無效。換句話說,我是否需要完全重新創建'httpRequest',是否應該避免在catch塊中調用httpRequest.abort(),並且只在最終失敗時調用它?

感謝

回答

7

的文件沒有提到會發生這樣的事情,雖然你也來試試吧。更重要的是,你應該考慮一些你的代碼...

  1. 你應該公開一些重試次數,允許調用者指定這個值。
  2. 如果發生異常,您應該只能重試;您目前正在重試,除非您獲得200.但是,例如,如果您獲得404 ...這並不意味着您的請求失敗,因爲網絡沒有失敗......相反,去服務器,但服務器根本沒有請求的資源......所以在這種情況下重試是沒有意義的。
  3. 按原樣,您可以禁止各種不同類型的異常。記錄列表中發生的所有異常並返回某種包含響應的結果對象(如果所有嘗試都失敗,可能爲空)可能是有意義的,除了所有異常列表之外。否則,您會從發生的一組異常中拋出一些任意異常,可能會導致失敗。
  4. 現在你只需要一遍又一遍地重複同樣的請求......如果出現擁塞,那麼你只需要添加它。如果你的IP地址被禁止了太多的活動,你可能會加入到這一點......任何類型的重試邏輯都應該具有退避行爲,在重試之間有一定的等待時間,並且該間隔隨着每次失敗。
3

我建議使用AOP和Java註解從jcabi-aspects(我是一個開發者):

@RetryOnFailure(attempts = 3, delay = 5) 
public String load(URL url) { 
    return url.openConnection().getContent(); 
}