就在昨天线上的X服务调用的Y服务须要上线,而后Y服务的ng路由作了改动。而后A服务的RestTemplate调用Y服务的某个接口开始报400!服务器
刚刚开始咱们觉得是ng路由配置的问题,由于咱们X服务并无作上线,以前也运行平稳,因此咱们就下意识的认为应该是Ng配置的缘由。可是当Ng配置还原以后,问题并无解决,仍旧是400!并发
而后咱们直接在X服务器上用curl访问Y服务的接口,访问正常!因此排除X服务问题,那么只有多是X服务出问题。可是X服务一直并无作上线呀,为何ng作了改动就这样了呢!curl
后面一直没找到问题,无奈之下重启了服务,问题再也不出现!高并发
整个自个人测试流程下来,其实基本能够定位到是A服务的问题,虽然他并无作改动,可是确定是外部的环境致使了A服务某个地方出现了问题。随后,咱们定位到了RestTemplate这个点!性能
疯狂找问题中。。。。测试
loading。。。。ui
最后发现咱们是将RestTemplate设置成了单例,而后初始化的时候用了HttpComponentsClientHttpRequestFactory。用这个是为了配置RestTemplate调用的时候的超时配置。编码
这个时候问题就来了!url
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
因为我是这样实例化HttpComponentsClientHttpRequestFactory,能够看到源码是:3d
由图可知HttpComponentsClientHttpRequestFactory默认用的是HttpClient,而后他的一个构建工厂HttpClientBuilder有一个属性是systemProperties。再看下面的源码:
当systemProperties这个属性为true的时候,HttpClient保持长链接了,并且接下去他会使用默认一个重用策略DefaultClientConnectionReuseStrategy。。。
坑爹啊,留下悔恨的眼泪。。。。
因此也就是说当我使用默认的初始化HttpComponentsClientHttpRequestFactory的时候,他默认会使用HttpClient的长链接。此时若是一旦出现调不通的状况,长链接在超时的时间内还会一直保持着链接,并且还会复用上一次错误的链接信息。所以咱们才会后续一直是400的状况,到咱们重启以后,长链接所有重置,又恢复如初。
因此解决这个问题只要在初始化HttpComponentsClientHttpRequestFactory的时候,传入自定义的HttpClient来实例HttpComponentsClientHttpRequestFactory,这样他就不会默认使用HttpClient的长链接,问题便可解决!
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
同时记得配置HttpClient最大链接数以及同路由并发数,防止高并发的时候RestTemplate的性能!
// 开始设置链接池 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(); // 最大链接数 poolingHttpClientConnectionManager.setMaxTotal(maxTotal); // 同路由并发数 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(maxPerRoute);、
当编码的时候,必定要思考详细,注意细节,要多看源码!不要想固然的直接引用公共的方法或类,当使用的时候应该看看源码,了解他的原理,是怎么运行的,必要的配置是否配齐!
同时加入详细全面的测试,如果详细的自测,这个问题也是会显露出来的!
今天记录下来这个问题,时刻勉励本身,细节必决定成败!