Im vorherigen Artikel (https://qiita.com/totto357/items/90f9276697edec08a4ba) habe ich vorgestellt, wie ein HTTP-Client nur mit Anmerkungen erstellt wird. Im eigentlichen HTTP-Client muss es jedoch erneut versucht werden. es gibt. Tatsächlich kann es viele Projekte geben, die eine HTTP-Client-Klasse mit "RestTemplate" erstellen und dort eine Wiederholungsverarbeitung durchführen.
Lassen Sie uns diesen Wiederholungsprozess mit "OpenFeign" realisieren.
Der Wiederholungsprozess von "OpenFeign" kann durch Implementierung von zwei Schnittstellen realisiert werden.
ErrorDecoder
ErrorDecoder
ist eine Schnittstelle zum Entscheiden, welche Art von Ausnahme
ausgelöst wird, wenn eine andere Antwort als die 200er in einer HTTP-Anforderung zurückgegeben wird.
Als Beispiel implementieren wir eine Klasse, die "IllegalArgumentException" zurückgibt, wenn sie "400" ist.
class IllegalArgumentExceptionOn404Decoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() == 400) {
throw new IllegalArgumentException("Es ist 400.");
}
return new ErrorDecoder.Default().decode(methodKey, response);
}
}
Grundsätzlich denke ich, dass Sie das Verhalten ändern können, indem Sie sich response.status ()
ansehen.
Wenn Sie RetryableException in decode
werfen, wird der folgendeRetryer.continueOrPropagate
Wird gerufen.
Retryer
Retryer
wird aufgerufen, wenn RetryableException
ausgelöst wird, und ist eine Schnittstelle zum Verwalten des Wiederholungsintervalls und der Häufigkeit.
Der Standard-Retryer ist Retryer.Default und wird 5 Mal in 100 ms versucht Es soll gemacht werden.
Wenn Sie nur das Wiederholungsintervall und die Häufigkeit ändern möchten, ist "Retryer.Default" meiner Meinung nach ausreichend.
Geben Sie die Ausführungsklasse der beiden oben genannten Schnittstellen in application.yml
an.
feign:
client:
config:
{{yourFeignName}}:
errorDecode: com.example.feign.MyErrorDecoder
retryer: com.example.feign.MyRetryer
Setzen Sie "yourFeignName" auf den in "FeignClient.name" angegebenen Wert. Wenn Sie "FeignClient.name" trennen, können Sie den Wiederholungsprozess für jeden "Namen" trennen.
Fügen wir dem vorherigen [Wetterbeispiel] einen Wiederholungsprozess hinzu (https://github.com/totto357/open-feign-client-example).
MyErrorDecoder.java In diesem Beispiel wird versucht, es erneut zu versuchen, wenn "503" und "504".
package com.example.ofc.feign;
import org.springframework.web.client.RestClientException;
import feign.Response;
import feign.RetryableException;
import feign.codec.ErrorDecoder;
public class MyErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
RestClientException cause = new RestClientException(response.toString());
final int status = response.status();
if (status == 503 || status == 504) {
return new RetryableException(methodKey, cause, null);
}
return cause;
}
}
MyRetryer.java Ich habe gerade Retryer.Default ein wenig geändert.
package com.example.ofc.feign;
import static java.util.concurrent.TimeUnit.SECONDS;
import feign.RetryableException;
import feign.Retryer;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyRetryer implements Retryer {
private final int maxAttempts;
private final long period;
private final long maxPeriod;
int attempt;
long sleptForMillis;
public MyRetryer() {
this(100, SECONDS.toMillis(1), 3);
}
public MyRetryer(long period, long maxPeriod, int maxAttempts) {
this.period = period;
this.maxPeriod = maxPeriod;
this.maxAttempts = maxAttempts;
this.attempt = 1;
}
// visible for testing;
protected long currentTimeMillis() {
return System.currentTimeMillis();
}
@Override
public void continueOrPropagate(RetryableException e) {
log.info("Wiederholen Sie die Verarbeitung");
if (attempt++ >= maxAttempts) {
throw e;
}
long interval;
if (e.retryAfter() != null) {
interval = e.retryAfter().getTime() - currentTimeMillis();
if (interval > maxPeriod) {
interval = maxPeriod;
}
if (interval < 0) {
return;
}
} else {
interval = nextMaxInterval();
}
try {
Thread.sleep(interval);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
throw e;
}
sleptForMillis += interval;
}
/**
* Calculates the time interval to a retry attempt. <br>
* The interval increases exponentially
* with each attempt, at a rate of nextInterval *= 1.5 (where 1.5 is the
* backoff factor), to the
* maximum interval.
*
* @return time in nanoseconds from now until the next attempt.
*/
long nextMaxInterval() {
long interval = (long) (period * Math.pow(1.5, attempt - 1));
return interval > maxPeriod ? maxPeriod : interval;
}
@Override
public Retryer clone() {
return new MyRetryer(period, maxPeriod, maxAttempts);
}
}
application.yml Geben Sie die beiden oben genannten Implementierungsklassen an.
server:
port: 8088
application:
name: open-feign-client
feign:
client:
config:
weather:
errorDecoder: com.example.ofc.feign.MyErrorDecoder
retryer: com.example.ofc.feign.MyRetryer
Ich habe versucht, die Wiederholungsverarbeitung mit "OpenFeign" zu realisieren. Es scheint einfach zu reparieren zu sein, da es realisiert werden kann, ohne den API-Client selbst zu berühren.
Klicken Sie hier für dieses Beispiel https://github.com/totto357/open-feign-client-example