首页 > 其他分享 >Spring Cloud全解析:服务调用之Feign的执行流程

Spring Cloud全解析:服务调用之Feign的执行流程

时间:2024-09-20 10:01:23浏览次数:1  
标签:body Feign 调用 return logLevel Spring response Cloud metadata

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 disconnected
      byte[] 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());
    }
  }
}

参考文献

标签:body,Feign,调用,return,logLevel,Spring,response,Cloud,metadata
From: https://www.cnblogs.com/life-time/p/18421914

相关文章