zoukankan      html  css  js  c++  java
  • feign使用okHttpClient,调用原理

    最近项目中 spring cloud 用到http请求,使用feign,配置okhttp,打算配置一下就直接使用,不过在压测与调优过程中遇到一些没有预测到的问题,附上排查与解析结

    yml、pom配置

    feign:
      client:
        config:
          default:
            connectTimeout: 2000
            readTimeout: 3000
            loggerLevel: FULL
      httpclient:
        enabled: false # 关闭 httpclient
      okhttp:
          enabled: true # 开启 okhttp
    <!-- feign-okhttp -->
    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-okhttp</artifactId>
        <version>4.2.2</version>
        <!-- <exclusions> -->
        <!-- 根据情况 -->
        <!-- </exclusions> -->
    </dependency>

    配置后,http请求没问题

    但在并发量100的场景下压测时,出现每个http请求相应时间达到100ms的情况,排查下游服务的反应时间很快,推测大量时间消耗在feign发起http请求

    怀疑okHttp的负载均衡可能有问题,我的服务发现使用consul,也很好奇okhttp是怎么实现的负载均衡,继续排查:

    配置feign配置类

    @Bean
    @ConditionalOnMissingBean
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) throws NoSuchAlgorithmException, KeyManagementException {
    SSLContext ctx = SSLContext.getInstance("SSL");
    X509TrustManager tm = new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    @Override
    public X509Certificate[] getAcceptedIssuers() {
    return null;
    }
    };
    ctx.init(null, new TrustManager[]{tm}, null);
    return new LoadBalancerFeignClient(new Client.Default(ctx.getSocketFactory(), (hostname, session) -> {
    // TODO Auto-generated method stub
    return true;
    }), cachingFactory, clientFactory);
    }

    这里配置使用 LoadBalancerFeignClient,配置后,100并发下效果仍然不佳

    经排查,代码中调用feign就耗费了100ms左右,只能深入看代码查原因,找一条响应时间长的case,看feign内部时间具体消耗在哪里:

     

     这里clientName为consul配置的服务发现名,比如配置里

    feign:
      service:
        order: test-name
    在feignClient里配置解析后,这里直接拿到的就是"test-name",然后通过lbClient去请求consul集群,获取到ip+port
    也就是说,okhttpClient不直接支持负载均衡,只是请求的执行者,在其之前由 LoadBalancerFeignClient 获取实例

     到这里,响应时间都很长,还需要继续深入

    FeignLoadbalancer,在这里可以看出是否实际使用了okhttp:

     

    继续排查,发现发送http请求很快,但最简单的encode,decode出现时间长的情况

    org.springframework.cloud.openfeign.support.SpringDecoder

    问题在这里,每次使用http请求,都new HttpMessageConverterExtractor,费时费力,导致并发量高时load、响应时间都高了

    解决方案

    在feign配置类里,指定decoder,不要每次new

    @Bean
    public Decoder feignDecoder() {
        ObjectMapper mapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .registerModule(new Jdk8Module())
            //fix LocalDateTime 无法序列化问题
            .registerModule(new JavaTimeModule());
        return new JacksonDecoder(mapper);
    }

    重新验证,100并发下响应时间降低到20ms,接近下游服务响应时间,http请求已不是瓶颈

    micheal.li > 阿智
    micheal.li > mikeve@163.com
  • 相关阅读:
    构建布局良好的Windows程序
    新认知之WinForm窗体程序
    分组查询之牛刀小试!
    Azure虚拟机时间同步问题
    关闭同一网络内的windows主机
    关于jdbc和数据库连接池的关系(不是封装的关系)
    spring,springMVC的优点和区别
    从新向你学习javase(第一天)
    spring包
    事物
  • 原文地址:https://www.cnblogs.com/loveCheery/p/14336298.html
Copyright © 2011-2022 走看看