• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

feign使用okHttpClient,调用原理

其他 开心洋葱 1344次浏览 0个评论

最近项目中 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内部时间具体消耗在哪里:

feign使用okHttpClient,调用原理 

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

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

feign使用okHttpClient,调用原理

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

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

feign使用okHttpClient,调用原理 

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

org.springframework.cloud.openfeign.support.SpringDecoder

feign使用okHttpClient,调用原理

问题在这里,每次使用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请求已不是瓶颈

 


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明feign使用okHttpClient,调用原理
喜欢 (1)

您必须 登录 才能发表评论!

加载中……