Open seaswalker opened 3 years ago
SynchronousMethodHandler的executeAndDecode方法:
Object executeAndDecode(RequestTemplate template) throws Throwable { Request request = targetRequest(template); Response response; long start = System.nanoTime(); try { response = client.execute(request, options); } catch (IOException e) { throw errorExecuting(request, e); } }
errorExecuting方法抛出了RetryableException:
static FeignException errorExecuting(Request request, IOException cause) { return new RetryableException( format("%s executing %s %s", cause.getMessage(), request.httpMethod(), request.url()), request.httpMethod(), cause, null); }
而feign正是通过判断catch到RetryableException来进行重试,invoke方法:
@Override public Object invoke(Object[] argv) throws Throwable { RequestTemplate template = buildTemplateFromArgs.create(argv); Retryer retryer = this.retryer.clone(); while (true) { try { return executeAndDecode(template); } catch (RetryableException e) { try { retryer.continueOrPropagate(e); } catch (RetryableException th) { Throwable cause = th.getCause(); if (propagationPolicy == UNWRAP && cause != null) { throw cause; } else { throw th; } } continue; } } }
接口调用时常见的异常: ConnectException(连接超时)、SocketTimeoutException(读超时),都是IOException的子类,而且写入超时更是直接抛出IOException.
ConnectException
SocketTimeoutException
还是SynchronousMethodHandler的executeAndDecode:
Object executeAndDecode(RequestTemplate template) throws Throwable { Request request = targetRequest(template); Response response; response = client.execute(request, options); boolean shouldClose = true; if (response.status() >= 200 && response.status() < 300) { // ... } else if (decode404 && response.status() == 404 && void.class != metadata.returnType()) { // ... } else { // 入口在这里 throw errorDecoder.decode(metadata.configKey(), response); } }
feign.codec.Default.decode:
@Override public Exception decode(String methodKey, Response response) { FeignException exception = errorStatus(methodKey, response); Date retryAfter = retryAfterDecoder.apply(firstOrNull(response.headers(), RETRY_AFTER)); if (retryAfter != null) { return new RetryableException( exception.getMessage(), response.request().httpMethod(), exception, retryAfter); } return exception; }
所以,当响应码是429,并且存在retry-after响应头时才会进行重试,当然重试的前提是配置了feign的Retryer. 这里使用的feign版本是10.1.0.
retry-after
Retryer
出现IOException
SynchronousMethodHandler的executeAndDecode方法:
errorExecuting方法抛出了RetryableException:
而feign正是通过判断catch到RetryableException来进行重试,invoke方法:
接口调用时常见的异常:
ConnectException
(连接超时)、SocketTimeoutException
(读超时),都是IOException的子类,而且写入超时更是直接抛出IOException.429, HttpTooManyRequests
还是SynchronousMethodHandler的executeAndDecode:
feign.codec.Default.decode:
所以,当响应码是429,并且存在
retry-after
响应头时才会进行重试,当然重试的前提是配置了feign的Retryer
. 这里使用的feign版本是10.1.0.