簡體   English   中英

如何在 Apache httpclient 中使用指數退避策略?

[英]How to use an Exponential Backoff strategy with Apache httpclient?

文檔指定了一個 ExponentialBackOffSchedulingStrategy 類,但它似乎在 4.5 版中不存在。

此外,沒有找到任何解釋如何使用它的內容。

以前有人用過這樣的東西嗎?

如果您使用這樣的 Maven 包安裝了 Apache HTTP Client 4.5.x(Grails Maven 依賴語法):

compile "org.apache.httpcomponents:httpclient:4.5.1"
compile "org.apache.httpcomponents:httpcore:4.4.3"

您需要添加另一個 jar 來獲取這些類,如下所示:

compile 'org.apache.httpcomponents:httpclient-cache:4.5.1'

https://hc.apache.org/httpcomponents-client-4.5.x/download.html

然后你可以像這樣連接它:

 import org.apache.http.impl.client.*;
 import org.apache.http.impl.client.cache.*;
 import org.apache.http.client.methods.*;

 CloseableHttpClient createClient() {
     CachingHttpClientBuilder hcb = new CachingHttpClientBuilder();
     CacheConfig cc = CacheConfig.DEFAULT;
     ExponentialBackOffSchedulingStrategy ebo = new ExponentialBackOffSchedulingStrategy(cc);
     hcb.setSchedulingStrategy(ebo);
     CloseableHttpClient hc = hcb.build();
     return hc;
 }

 // You'll need to replace the URL below with something that returns a 5xx error
 CloseableHttpClient client = createClient();
 HttpUriRequest request = new HttpGet("http://www.example.com/throwsServerError");
 for (int i=0; i<4; i++) {
     CloseableHttpResponse response =  client.execute(request);
     println new Date().toString() + " " + response.getStatusLine().getStatusCode();
 }

ExponentialBackOffSchedulingStrategy適用於緩存條目,這就是它只能與CachingClient一起使用的CachingClient 我認為它不能用於對失敗的請求實現指數退避重試機制。

我將沿着這些路線實施一個簡單的指數退避策略:

class MyExponentialBackoffRetryHandler extends HttpRequestRetryHandler {
  public MyExponentialBackoffRetryHandler(int maxNumRetries, int backOffRate, int initialExpiry, int maxExpiry) {
  } 
 boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
   if (executionCount == maxNumRetries) {
     return false;
   }else {
     long nextBackOffDelay = initialExpiry * Math.pow(backOffRate, executionCount - 
1)
     long delay = Math.min(maxExpiry, nextBackOffDelay)
     Thread.sleep(delay);
     return true;
   } 

}
}

此外,為了觸發重試,您需要添加一個拋出IOException的響應攔截器,例如:

class MyResponseInterceptor extends HttpResponseInterceptor {
  void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
    if (response.getStatusLine.getStatusCode == 503) {
        throw new IOException("Please retry")
    }
  }
}

最后,您可以構建 HTTP 客戶端實例,如下所示:

HttpClientBuilder
    .create()
    .setRetryHandler(new MyExponentialBackoffRetryHandler(...))
    .addInterceptorFirst(new MyResponseInterceptor())
    .build()

您可以通過向https://httpstat.us/503發送請求來輕松測試客戶端

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM