SpringCloud FeignClient的坑(httpClient连接池的使用)
前言
在头条上已经发布过不少的文章了,根据文章的浏览量来看,go语言的市场需求明显是小于java的需求量的,最近也开始发布一下以前使用java和springcloud,springboot里遇到的一些避坑文章; 个人感觉go在云原生这个场景里将会不断的被发展,在云原生环境下,没有任何一个语言可能和其匹敌,RUST也许会有一定的竞争压力。 作为service mesh未来的云环境架构, springcloud的原有项目会慢慢的转换; 先说了些感悟, 今天要分享的是OpenFeign里的一个小坑。 OpenFeign是springcloud里用的比较多的http RPC的一个架构, FeignClient是这个架构中的一个Client的入口点。
现象:
压力测试
结果发现,并发线程数较多(>40)时,持续一段时间后,请求总数差不多达到100万时,开始出现请求失败。这个错误比例在10%~30%之间。
看日志,发现错误有两种:
一种是ribbon报找不到目标服务,错误信息如下:
Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: halo-framework-example-server
at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483)
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184)
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94)
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42)at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_152]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_152]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_152]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_152]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_152]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_152]
at sun.net.NetworkClient.doConnect(NetworkClient.java:175) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:463) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:558) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.New(HttpClient.java:339) ~[na:1.8.0_152]
at sun.net.www.http.HttpClient.New(HttpClient.java:357) ~[na:1.8.0_152]
查看feignclient调用代码
如下:
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
OkHttpFeignLoadBalancedConfiguration.class,
DefaultFeignLoadBalancedConfiguration.class })
public class FeignRibbonClientAutoConfiguration {
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
class HttpClientFeignLoadBalancedConfiguration {
上面是autoconfiguration的方式对feignClient进行配置。 可以看到有三种方式, 分别是HttpClientFeignLoadBalancedConfiguration.class, OkHttpFeignLoadBalancedConfiguration.class,
DefaultFeignLoadBalancedConfiguration.class
这三种方式, 其中最后一种方式DefaultFeignLoadBalancedConfiguration是默认方式,也就是直接通过Httpclient进行http的调用,不使用连接池的方式,只有上面两种方式是支持连接池的方式, Openfeign组件通过类型ConditionONClass的方式,进行条件配置,如果引入了OKHttpClient或者Apache HttpClient的包才会使用到http的连接池, 由于默认是没有import这里的两个包,所以默认以不带连接池的实现方式来实现httpclient,也就出现上面的问题。
知道了问题所在,解决的方法,就是引入相应的包即可。
标签:152,java,SpringCloud,1.8,na,net,HttpClient,连接池,httpClient From: https://blog.51cto.com/u_9748604/5776893