Spring Cloud全解析:服务调用之Feign的执行流程
文章目录
- Feign的执行流程
Feign的执行流程
-
首先通过@EnableFeignClients注解开启Feign功能,程序启动时开启对@FeignClient注解的扫描
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(FeignClientsRegistrar.class) public @interface EnableFeignClients
-
当接口的方法调用时,通过动态代理SynchronousMethodHandler生成具体的RequestTemplate
public Object invoke(Object[] argv) throws Throwable {RequestTemplate template = buildTemplateFromArgs.create(argv);Options options = findOptions(argv);Retryer retryer = this.retryer.clone();while (true) {try {return executeAndDecode(template, options);} catch (RetryableException e) {try {retryer.continueOrPropagate(e);} catch (RetryableException th) {Throwable cause = th.getCause();if (propagationPolicy == UNWRAP && cause != null) {throw cause;} else {throw th;}}if (logLevel != Logger.Level.NONE) {logger.logRetry(metadata.configKey(), logLevel);}continue;}} }
RequestTemplate template = buildTemplateFromArgs.create(argv);
在构建RequestTemplate的时候会进行参数解析,如果参数是@RequestBody的会调用Encoder的encode方法进行编码(BuildEncodedTemplateFromArgs)
encoder.encode(body, metadata.bodyType(), mutable);
-
再根据RequestTemplate生成HTTP的Request对象
-
Request对象交给Client处理,可配置HttpURLConnection、HttpClient、OkHttp等
// 该方法首先会调用RequestInterceptor的apply方法处理请求,之后才会进行请求发送 // 执行完之后调用Decoder的decode方法来进行解码 return executeAndDecode(template, options);
-
Client被封装到LoadBalanceClient类进行负载均衡
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {// 调用RequestInterceptor的apply方法处理请求Request request = targetRequest(template);if (logLevel != Logger.Level.NONE) {logger.logRequest(metadata.configKey(), logLevel, request);}Response response;long start = System.nanoTime();try {// 请求发送response = client.execute(request, options);} catch (IOException e) {if (logLevel != Logger.Level.NONE) {logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));}throw errorExecuting(request, e);}long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);boolean shouldClose = true;try {if (logLevel != Logger.Level.NONE) {response =logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);}if (Response.class == metadata.returnType()) {if (response.body() == null) {return response;}if (response.body().length() == null ||response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {shouldClose = false;return response;}// Ensure the response body is disconnectedbyte[] bodyData = Util.toByteArray(response.body().asInputStream());return response.toBuilder().body(bodyData).build();}if (response.status() >= 200 && response.status() < 300) {if (void.class == metadata.returnType()) {return null;} else {//调用Decoder的decode方法来进行解码Object result = decode(response);shouldClose = closeAfterDecode;return result;}} else if (decode404 && response.status() == 404 && void.class != metadata.returnType()) {Object result = decode(response);shouldClose = closeAfterDecode;return result;} else {// 调用ErrorDecoder进行错误解码throw errorDecoder.decode(metadata.configKey(), response);}} catch (IOException e) {if (logLevel != Logger.Level.NONE) {logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);}throw errorReading(request, response, e);} finally {if (shouldClose) {ensureClosed(response.body());}}
}
参考文献
- Feign的执行流程