SpringBoot项目中ES High Level Rest Client 超时问题排查及解决( 二 )


②抛出异常时间段不固定 。
问题定位
这个问题在之前开发多集群管理平台的时候也出现,当时因为存在③跨版本且还没有正式投产的情况下,并没有太关注的此类问题,觉得此问题可能是版本兼容性 。项目组报上来问题才认真地排查了一番 。
应用系统通过ES High Level Rest Client客户端直连且版本相同,可以排查③的情况 。起初怀疑是查询或者写入量大,后台处理不及时的原因导致异常 。于是查看监控数据和日志,监控显示在几次出现异常的时间点上各项指标这都很正常,没有出现流量陡增的情况,结合现象②,可以排除是因为服务端压力的原因 。
接着把影响异常的源头定位在客户端 。ES客户端和服务端的连接采用的是长连接,查阅源码发现客户端创建了client连接池,每个client持有一个http连接,并且开启http的keep-alive策略复用连接 。正是因为这个复用探活的原因导致该异常发生 。下面具体分析该问题 。
问题分析
在未处理前restClient客户端创建示意代码:
final RestClientBuilder restClientBuilder =RestClient.builder(redisHostList).setRequestConfigCallBack(requestConfigBuilder -> {;requestConfigBuilder.setConnectTimeout(5000);requestConfigBuilder.setSocketTimeout(60000);requestConfigBuilder.setConnectionRequestTimeout(500);return requestConfigBuilder;}).setHttpClientConfigCallback((httpAsyncClientBuilder) -> {httpAsyncClientBuilder.disableAuthCacheing();return httpAsyncClientBuilder;final RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder);客户端与服务端的连接示意图:
 

SpringBoot项目中ES High Level Rest Client 超时问题排查及解决

文章插图
 
 
ES high-level-client 对长连接的实现是把超时时间设置为-1,意味着客户端永远不超时,服务端设备为了资源的利用率会检测与此设备的连接是否在使用,如果一个连接长时间没有使用,服务端会主动把这个连接关闭,而此时客户端不知情,还处在连接状态,可以说当前处于半连接状态 。当有流量进来的时候使用了该连接就会发现与服务端连接不上,产生timeout,客户端也断开此链接,如上图 1 所示 。客户端使用新连接 2 与服务端通信 。因此问题的根源在于客户端没有及时发现连接的不可用并断开,因此需要设置让客户端主动对tcp连接进行探测保活 。
解决方案
一、客户端显式的设置setKeepAliveStrategyhttpAsyncClientBuilder.setKeepAliveStrategy((httpResponse,httpContext) -> TimeUtils.MINUTES.toMillis(3))二、显示开启 tcp keepalivehttpAsyncClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.sustom().setSoKeepAlive(true).build())三、在系统层面设置tcp keepalive探测保活时间net.ipv4.tcp_keepalive_time = 60来源:
https://www.modb.pro/db/388569

【SpringBoot项目中ES High Level Rest Client 超时问题排查及解决】


推荐阅读