ES报错:Connection reset by peer解决经历

项目场景:

Spring boot集成spring-data-elasticsearch4.4.10, 使用ElasticsearchRestTemplate. es为个人在容器内拉去镜像搭建,不需要用户名密码


问题描述

每隔20分钟报错:Connection reset by peer; nested exception is java.lang.RuntimeException: Connection reset by peer


原因分析:

1.查看es容器是否有报错,排查结果无报错

$ curl 'localhost:9200/_cat/health'  # 查询节点健康状况
$ curl 'localhost:9200/_cat/indices?v'  #查看集群中所有索引的详细信息。包括索引的健康度、状态、分片数和副本数、包含的文档数等
$ curl 'localhost:9200/_cluster/health'  #查询集群的健康状态
$ curl 'localhost:9200/_cluster/allocation/explain' #定位未分配问题

2.查看服务端keepalive,为两小时,与观察到的20分钟现象不符合(当前情况应属于服务端断开连接,不需要查看客户端keepalive)

root@es7-5ffdd5b7fc-zfqft:/usr/share/elasticsearch# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200

3.由于项目部署在阿里云k8s容器内,检查容器内是否开启tcp健康检查,tcp健康检查的默认频率很快,会频繁扫描端口,网络不好时会导致断连

4.可能是防火墙的原因,查询资料:防火墙上的各会话缺省保持时间都相对较短,例如:缺省情况下,TCP的保持时间为1200s,UDP的保持时间为120s

此时基本锁定防火墙


解决方案:

方案一:自行编写心跳代码
该方法尝试了时间间隔5分钟,2分钟,1分钟,10秒还是会偶尔出现报错

    @Scheduled(cron = "*/10 * * * * * ")
    @Async
    public void heartbeatTask() {
        //todo 执行es查询
    }

方案二:设置保活机制
主要关注httpClient设置保活策略,这里设置为5分钟。该方案可以彻底解决问题

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

import java.time.Duration;

@Configuration
@EnableElasticsearchRepositories(basePackages = "com.example.test")
//@ComponentScan(basePackages = { "com.example.test" })
public class ElasticRestClientConfig {

    @Value("${spring.elasticsearch.rest.uris}")
    private String url;
//    @Value("${spring.elasticsearch.rest.username}")
//    private String username;
//    @Value("${spring.elasticsearch.rest.password}")
//    private String password;

    @Bean
    public RestHighLevelClient client() {
        url = url.replace("http://","");
        String[] urlArr = url.split(",");
        HttpHost[] httpPostArr = new HttpHost[urlArr.length];
        for (int i = 0; i < urlArr.length; i++) {
            HttpHost httpHost = new HttpHost(urlArr[i].split(":")[0].trim(),
                    Integer.parseInt(urlArr[i].split(":")[1].trim()), "http");
            httpPostArr[i] = httpHost;
        }
        /** 提供密码登录代码相关代码 本项目不需要密码登录
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username,password));*/
        RestClientBuilder builder = RestClient.builder(httpPostArr)
                // 异步httpclient配置
                .setHttpClientConfigCallback(httpClientBuilder -> {
                    // 账号密码登录
//                    httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    // httpclient连接数配置
                    httpClientBuilder.setMaxConnTotal(30);
                    httpClientBuilder.setMaxConnPerRoute(10);
                    // httpclient保活策略
                    httpClientBuilder.setKeepAliveStrategy(((response, context) -> Duration.ofMinutes(5).toMillis()));
                    return httpClientBuilder;
                });
        return new RestHighLevelClient(builder);
    }

    @Bean
    public ElasticsearchRestTemplate elasticsearchRestTemplate() {
        return new ElasticsearchRestTemplate(client());
    }
}
  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值