ES两个小时没连接竟然会出现bug,为此老板给我夹了个鸡腿。。。

发布时间:2024年01月05日

前言

前段时间上线了个项目,测试每天早上来摸鱼之前会点一点,发现第一次点会报错,然后一天都没问题,刚开始没在意,后来每天上班来摸鱼前点第一次都会出错,发现真的摸到鱼了,然后就给我提了个bug,说明天早上第一次留给你,你复现一下看看,然后就有了这篇文章了。

问题现象

ES隔一段时间不操作后,再请求es就会报错Connection reset by peer,之后连续几次操作都正常,而且还是必现的,报错信息如下:

 

css

复制代码

org.springframework.dao.DataAccessResourceFailureException: Connection reset by peer; nested exception is java.lang.RuntimeException: Connection reset by peer at org.springframework.data.elasticsearch.core.ElasticsearchExceptionTranslator.translateExceptionIfPossible(ElasticsearchExceptionTranslator.java:76) at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.translateException(ElasticsearchRestTemplate.java:378) ...... Caused by: java.io.IOException: Connection reset by peer at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:828) at org.elasticsearch.client.RestClient.performRequest(RestClient.java:248) at org.elasticsearch.client.RestClient.performRequest(RestClient.java:235) at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1514) ...... Caused by: java.io.IOException: Connection reset by peer at sun.nio.ch.FileDispatcherImpl.read0(Native Method) at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) ......

问题定位

Caused by: Connection reset by peer根据日志可以知道,socket 连接被中断,连接中断的原因有很多,比如:

  • 服务端或者客户端异常。
  • 客户端连接超时中断。

查看日志,这段时间内也没啥异常信息,服务端也没异常重启,也没出现流量陡量的情况。想到之前在mysql遇到过的问题,mysql的连接如果超过8个小时(默认的时间)不连接,服务端为了节约资源,会主动把长时间没连接的客户端给中断掉,按照这个思路去排查问题,果然发现原因如出一辙。导致这个问题的原因有两个:

  1. 客户端采用长连接的方式连接服务端。
  2. 长时间不连ES,服务端会关闭连接。
1. 客户端采用长连接的方式连接服务端, 一直持有连接。

ES High Level Rest Client客户端和服务端的连接采用的是长连接,查阅源码发现客户端创建了client连接池,每个client持有一个http连接,并且开启http的keep-alive策略复用连接, 策略默认是 -1 ,也就是不过期。

es1.png

2. 长时间不连ES,服务端会关闭连接。

服务器会有TCP的Keepalive 经过一段时间如果没有操作就会自动断开连接功能,而ES默认就是取服务器的时长配置linux查看超时时间默认为两小时:

 

csharp

复制代码

# 查看超时时间(单位秒) [root@VM ~]# cat /proc/sys/net/ipv4/tcp_keepalive_time 7200

也就是说如果客户端超过两个小时没有连接服务端,服务端会清除掉连接。

解决方法

修改客户端的keepalive时间,以单机的ES为例,代码如下:

 

ini

复制代码

@Override public RestHighLevelClient elasticsearchClient() { ? ?List<HttpHost> httpHostsList = new ArrayList<>(); ? ?httpHostsList.add(new HttpHost(uris, Integer.parseInt(port))); ? ?HttpHost[] httpHostsArray = new HttpHost[httpHostsList.size()]; ? ?httpHostsArray = httpHostsList.toArray(httpHostsArray); ? ?RestClientBuilder builder = RestClient.builder(httpHostsArray); ? ?builder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setKeepAliveStrategy((httpResponse, httpContext) -> 1000 * 60)); ? ?return new RestHighLevelClient(builder); }

application.yaml

 

yaml

复制代码

spring: elasticsearch: ? rest: ? ? uris: ip ? ? port: port

以上代码是基于单机版的es配置的,如果你们的是集群请自行百度设置,重点代码是设置setKeepAliveStrategy 这个方法里面。

经过这个设置后,线上就没有出现过类似的问题了。

最后

其实这个问题不仅仅是ES会有的,mysql, CK, 还有其他同类的C/S架构的都会存在这样的问题,这是一类问题,由于服务端资源优化,会回收一些连接,就会导致这个问题,知道这个问题后,我们可以举一反三,遇到同样的问题可以快速定位,希望这个问题能对大家有用,最后感谢大家看到这里。。。

作者:TodoCoder
链接:https://juejin.cn/post/7113706089350168606
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

文章来源:https://blog.csdn.net/qq_32907195/article/details/135409120
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。