Elasticsearch7.6解决报错Connection reset by peer【刨根问底完美解决】

Bertha 。 2023-10-04 20:51 147阅读 0赞

一、前言

小编最近在生产上遇到一个问题,解决完后立马总结一下分享给大家,希望可以帮助到大家哈!

事情是这样的,奇怪的现象,公司搭建的ElasticSearch,本来是用来提高检索效率的,最近出现报错了!

版本配置什么都没变,奇怪的很!

问题:
每隔几个小时就会查询不到,与ElasticSearch连接不上,刷新后查询正常
报错为:java.io.IOException: Connection reset by peer

拿着条件去kibana是可以查询到的;

核心原因:

这是客户端是长链接,服务端过期后自动关闭链接,客户端继续用原来的链接导致错误的!

二、前因后果

小编ElasticSearch版本为7.6
下面我们来详细说一下报错原因和解决方案哈:

1. 报错信息

  1. java.io.IOException: Connection reset by peer
  2. at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:828)
  3. at org.elasticsearch.client.RestClient.performRequest(RestClient.java:248)
  4. at org.elasticsearch.client.RestClient.performRequest(RestClient.java:235)
  5. at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1514)
  6. at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1484)
  7. at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1454)
  8. at org.elasticsearch.client.RestHighLevelClient.search(RestHighLevelClient.java:970)

2. 原因与解决方案

上面也是说了原因,但是不太详细,下面详细说一下原因哈!

ES会设置一个策略来进行链接时间的控制,设置此连接的空闲持续时间!

我们可以看一下这个策略:

这是我们不配置会走这个策略,默认-1为长链接,可循环重复使用;

我们只需要把这个策略换成我们的即可

  1. @Contract(threading = ThreadingBehavior.IMMUTABLE)
  2. public class DefaultConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {
  3. public static final DefaultConnectionKeepAliveStrategy INSTANCE = new DefaultConnectionKeepAliveStrategy();
  4. @Override
  5. public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {
  6. Args.notNull(response, "HTTP response");
  7. final HeaderElementIterator it = new BasicHeaderElementIterator(
  8. response.headerIterator(HTTP.CONN_KEEP_ALIVE));
  9. while (it.hasNext()) {
  10. final HeaderElement he = it.nextElement();
  11. final String param = he.getName();
  12. final String value = he.getValue();
  13. if (value != null && param.equalsIgnoreCase("timeout")) {
  14. try {
  15. return Long.parseLong(value) * 1000;
  16. } catch(final NumberFormatException ignore) {
  17. }
  18. }
  19. }
  20. return -1;
  21. }
  22. }

服务器的TCP时间,我们可以查看一下:

  1. cat /proc/sys/net/ipv4/tcp_keepalive_time

在这里插入图片描述

这里就是12分钟,我们需要让客户端的链接时间小于服务器的keepalive时间!

这样客户端超过时间后就会重新获取新链接,确保不会报错哈!!

三、具体方案

编写ElasticsearchProperties ,获取nacos上的信息,方便修改!

  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "spring.elasticsearch.rest")
  4. public class ElasticsearchProperties {
  5. private String uris;
  6. private String username;
  7. private String password;
  8. }

编写RestHighLevelClient配置类,使用我们的策略,看到其他教学还是使用以前的连接方式,现在RestClientBuilder里的RestClientBuilder是自动构建连接的!

这里我们把RestClientBuilder注入,继续放里面放新策略即可!

由于我们重写RestHighLevelClient,它又依赖RestClientBuilder,原来RestClientBuilder会自动获取用户名密码、连接地址,现在我们需要把用户名密码重新赋值一下哈!
这样就可以少一步输入地址的哈!

这里设置10分钟,没有超过12分钟!

  1. @Configuration
  2. public class ElasticsearchConfig {
  3. @Autowired
  4. private ElasticsearchProperties elasticsearchProperties;
  5. @Autowired
  6. private RestClientBuilder restClientBuilder;
  7. @Bean
  8. public RestHighLevelClient restHighLevelClient(){
  9. CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
  10. credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(elasticsearchProperties.getUsername(), elasticsearchProperties.getPassword()));
  11. return new RestHighLevelClient(restClientBuilder.setHttpClientConfigCallback(requestConfig ->{
  12. requestConfig.setKeepAliveStrategy((response, context) -> TimeUnit.MINUTES.toMillis(10));
  13. requestConfig.setDefaultCredentialsProvider(credentialsProvider);
  14. return requestConfig;
  15. }));
  16. }
  17. }

看一下配置文件:

在这里插入图片描述

方案二:

如果不介意的话可以把错误捕获起来,重新调用一下,第二次就会重新建立连接,这样就不会有问题了,不过这种不太建议!!

四、总结

这样就完美解决了,生产回复正常哈!

写作不易,大家给点支持,你的支持是我写作的动力哈!

对你有帮助,还请不要吝啬你的发财小手点点关注哈!

关注小编的微信公众号,一起交流学习!文章首发看哦!

发表评论

表情:
评论列表 (有 0 条评论,147人围观)

还没有评论,来说两句吧...

相关阅读