2016-06-17 34 views
7

Ustawiam opcję ponów próbę połączenia na OkHttpClient.Czy OkHttpClient ma maksymalną liczbę ponownych prób

client = new OkHttpClient(); 
client.setRetryOnConnectionFailure(true); 

Chciałbym wiedzieć, ile razy będzie próbować. Patrząc na source code nie widziałem żadnego maksymalnego limitu. Jak skonfigurować klienta, aby przestał próbować po kilku próbach?

Odpowiedz

5

Istnieje więcej docs tutaj https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.Builder.html#retryOnConnectionFailure-boolean-

skonfigurować ten klient, aby ponowić próbę lub gdy problem nie jest łączność spotkałem. Domyślnie klient cicho odzyskuje od następujących problemów:

  • nieosiągalne adresy IP. Jeśli host URL ma wiele adresów IP, niepowodzenie w uzyskaniu indywidualnego adresu IP nie zawiedzie ogólnego żądania. Może to zwiększyć dostępność usług wieloadresowych.
  • Stale połączone połączenia. ConnectionPool ponownie wykorzystuje gniazda, aby zmniejszyć opóźnienie żądania, ale połączenia te czasami się kończą.

  • Nieosiągalne serwery proxy. ProxySelector może być używany do próbowania wielu serwerów proxy po kolei, ostatecznie wracając do bezpośredniego połączenia.

Ustaw tę wartość na false, aby uniknąć ponawiania próśb, gdy jest to destrukcyjne. W takim przypadku aplikacja wywołująca powinna samodzielnie odzyskać awarie łączności.

Generalnie sądzę, że ma on na celu ponowienie próby w przypadku istniejącego nieaktualnego połączenia lub alternatywnych ścieżek, które mogą zostać ponownie sprawdzone. Nie powtarzać dokładnie tego samego w nieskończoność.

zobaczyć również ConnectionSpecSelector.connectionFailed

+0

To także moje zrozumienie. Ponadto spróbuje ponownie wykonać nieudany handshake SSL. Ale nie wydaje się, aby ponowić próbę natychmiastowego błędu połączenia TCP. – RajV

1

Nie ma wbudowanej metody ustawiania limitu maksymalnego, ale można dodać przechwytywacz, jak poniżej.

client.interceptors().add(new Interceptor() { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Request request = chain.request(); 

     // try the request 
     Response response = chain.proceed(request); 

     int tryCount = 0; 
     int maxLimit = 3; //Set your max limit here 

     while (!response.isSuccessful() && tryCount < maxLimit) { 

      Log.d("intercept", "Request failed - " + tryCount); 

      tryCount++; 

      // retry the request 
      response = chain.proceed(request); 
     } 

     // otherwise just pass the original response on 
     return response; 
    } 
}); 

Więcej szczegółów na temat interceptos można znaleźć here.

+0

response.isSuccessful() sprawdza czy kod stanu HTTP. Czy to zadziała w przypadku awarii połączenia? – RajV

+0

Tak. jeśli kod odpowiedzi to 2xx lub 3xx, 'isSuccessful()' zwróci "true". Dla odpoczynku zwróci wartość "false". A awarie połączenia są w większości 4xx, więc powinno działać. –

+0

Błąd połączenia TCP oznacza, że ​​nie można wysłać żądania HTTP ani uzyskać odpowiedzi. Nie wiem, jak kod statusu będzie 4xx. – RajV

2

zrobiłem poniżej rozwiązania:

@Override 
public Response intercept(Chain chain) throws IOException { 
    Request request = chain.request(); 
    // try the request 
    Response response = doRequest(chain,request); 
    int tryCount = 0; 
    while (response == null && tryCount <= RetryCount) { 
    String url = request.url().toString(); 
    url = switchServer(url); 
    Request newRequest = request.newBuilder().url(url).build(); 
    tryCount++; 
    // retry the request 
    response = doRequest(chain,newRequest); 
    } 
    if(response == null){//important ,should throw an exception here 
     throw new IOException(); 
    } 
    return response; 
} 

private Response doRequest(Chain chain,Request request){ 
    Response response = null; 
    try{ 
     response = chain.proceed(request); 
    }catch (Exception e){ 
    } 
    return response; 
} 
+0

To działa idealnie dla mnie. Wielkie dzięki. – yoavgray