自学内容网 自学内容网

Elasticsearch节点故障怎么处理?

java.util.concurrent.TimeoutException: Connection lease request time out at org.apache.http.nio.pool.AbstractNIOConnPool.processPendingRequest(AbstractNIOConnPool.java:411) at org.apache.http.nio.pool.AbstractNIOConnPool.processNextPendingRequest(AbstractNIOConnPool.java:391) at org.apache.http.nio.pool.AbstractNIOConnPool.release(AbstractNIOConnPool.java:355) at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.releaseConnection(PoolingNHttpClientConnectionManager.java:391) at org.apache.http.impl.nio.client.AbstractClientExchangeHandler.releaseConnection(AbstractClientExchangeHandler.java:245) at org.apache.http.impl.nio.client.MainClientExec.responseCompleted(MainClientExec.java:387) at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted(DefaultClientExchangeHandlerImpl.java:172) at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:448) at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:338) at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:265) at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81) at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39) at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:114) at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162) at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337) at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315) at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276) at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104) at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591) at java.lang.Thread.run(Thread.java:745) 11:19:21.751 [I/O dispatcher 2] ERROR c.m.w.c.c.e.EsConfiguration - [onFailure,85] - 某个节点发生故障,故障地址是http://114.124.145.114:9200 11:19:21.751 [I/O dispatcher 2] ERROR c.m.w.c.c.e.EsOperationClient - [onFailure,69] - es异步插入失败=

插入的数据不能一下子大批量的执行,要分页!!!!!!!!!!!!!!!!!!!!!

分析

从提供的错误信息来看,java.util.concurrent.TimeoutException: Connection lease request time out 表示在尝试获取连接时超时了。这通常是由于以下几种原因之一:

  1. 网络问题:Elasticsearch 节点不可达或网络延迟高。
  2. 连接池配置问题:连接池的大小或超时时间设置不合理。
  3. Elasticsearch 节点负载过高:Elasticsearch 节点处理请求的速度较慢,导致连接池中的连接被占用时间过长。
  4. 客户端配置问题:客户端的超时时间设置过短。

解决方案

  1. 检查网络连接

    • 确保 Elasticsearch 节点 http://114.115.178.114:9200 可达。
    • 使用 pingcurl 命令测试网络连接:
      ping 114.115.178.114
      curl -X GET "http://114.115.178.114:9200/_cluster/health?pretty"
      
  2. 调整连接池配置

    • 增加连接池的最大连接数。
    • 增加连接超时时间。
  3. 优化 Elasticsearch 节点

    • 检查 Elasticsearch 节点的负载情况,确保其有足够的资源处理请求。
    • 如果负载过高,可以考虑增加节点或优化索引和查询性能。
  4. 调整客户端配置

    • 增加客户端的超时时间。

修改代码

以下是修改后的代码,增加了连接池配置和客户端超时时间:

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;

public class ElasticsearchClientConfig {

    public static RestHighLevelClient createClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("username", "password"));

        RestClientBuilder builder = RestClient.builder(
                new HttpHost("114.115.178.114", 9200, "http"))
                .setHttpClientConfigCallback(new HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
                                .setMaxConnTotal(100) // 增加最大连接数
                                .setMaxConnPerRoute(20); // 增加每个路由的最大连接数
                    }
                })
                .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
                    @Override
                    public org.apache.http.client.config.RequestConfig.Builder customizeRequestConfig(org.apache.http.client.config.RequestConfig.Builder requestConfigBuilder) {
                        return requestConfigBuilder
                                .setSocketTimeout(60000) // 增加套接字超时时间
                                .setConnectTimeout(60000) // 增加连接超时时间
                                .setConnectionRequestTimeout(60000); // 增加连接请求超时时间
                    }
                });

        return new RestHighLevelClient(builder);
    }

    public static void main(String[] args) {
        RestHighLevelClient client = createClient();
        // 使用 client 进行操作
        // ...
        try {
            // 你的操作代码
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

关键点说明

  1. 连接池配置

    • setMaxConnTotal(100):设置连接池的最大连接数为100。
    • setMaxConnPerRoute(20):设置每个路由的最大连接数为20。
  2. 客户端超时时间

    • setSocketTimeout(60000):设置套接字超时时间为60秒。
    • setConnectTimeout(60000):设置连接超时时间为60秒。
    • setConnectionRequestTimeout(60000):设置连接请求超时时间为60秒。

运行代码

运行上述代码,确保连接池配置和超时时间设置合理。如果问题仍然存在,可以通过日志输出和网络监控工具进一步排查问题。

其他建议

  1. 监控 Elasticsearch 节点

    • 使用 Kibana 或其他监控工具监控 Elasticsearch 节点的健康状况和性能指标。
    • 检查日志文件,查看是否有其他错误或警告信息。
  2. 优化查询

    • 确保查询条件和索引设计合理,避免全表扫描。
    • 使用合理的分页参数,避免一次性返回大量数据。

设置下集群配置类的超时时间和查询ES的分页大小

/**
 * es集群配置类
 * @author sunpeiyang
 * @date 2024/11/7 17:22
 */
@Slf4j
@Configuration
public class EsConfiguration {
    private static final int ADDRESS_LENGTH = 2;

    private static final String HTTP_SCHEME = "http";

    @Value("${es.hosts:114.23.45.22:9200}")
    private String[] hosts;

    @Value("${es.username:elastic}")
    private String username;

    @Value("${es.password:elastic}")
    private String password;

    @Value("${es.connectTimeout:60000}")
    private Integer connectTimeout;

    @Value("${es.socketTimeout:60000}")
    private Integer socketTimeout;

    @Value("${es.connectionRequestTimeout:60000}")
    private Integer connectionRequestTimeout;

    public CredentialsProvider basicCredentialsProvider() {
        if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials(username, password));
            return credentialsProvider;
        }
        return null;
    }

    @Bean
    public RestClientBuilder restClientBuilder() {
        HttpHost[] httpHosts = Arrays.stream(hosts)
                .map(this::getHttpHost)
                .filter(Objects::nonNull)
                .toArray(HttpHost[]::new);
        RestClientBuilder builder = RestClient.builder(httpHosts);
        CredentialsProvider credentialsProvider = basicCredentialsProvider();
        if (credentialsProvider != null) {
            builder.setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
            builder.setRequestConfigCallback(requestConfigBuilder -> {
                //设置连接超时时间
                requestConfigBuilder.setConnectTimeout(connectTimeout);
                //设置socket超时时间s
                requestConfigBuilder.setSocketTimeout(socketTimeout);
                //设置连接请求超时时间
                requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
                return requestConfigBuilder;
            });
            builder.setFailureListener(new RestClient.FailureListener() {
                /*3.设置每次节点发生故障时收到通知的侦听器。内部嗅探到故障时被启用。*/
                @Override
                public void onFailure(Node node) {
                    log.error("某个节点发生故障,故障地址是" + node.getHost());
                }
            });
        }
        return builder;
    }

    @Bean(name = "highLevelClient")
    public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
        return new RestHighLevelClient(restClientBuilder);
    }


    private HttpHost getHttpHost(String host) {
        assert StringUtils.isNotEmpty(host);
        String[] address = host.split(":");
        if (address.length == ADDRESS_LENGTH) {
            String ip = address[0];
            int port = Integer.parseInt(address[1]);
            return new HttpHost(ip, port, HTTP_SCHEME);
        } else {
            return null;
        }
    }

}

使用Elasticsearch需要注意什么?

使用 Elasticsearch 时,除了理解其基本功能和配置外,还需要关注一些关键的最佳实践和性能优化措施。以下是使用 Elasticsearch 时需要注意的几个重要方面:

1. 硬件和资源配置

Elasticsearch 是一个内存密集型的应用,合理的硬件资源配置对于性能至关重要。

内存:Elasticsearch 强烈依赖于 JVM 堆内存(Heap Memory)。推荐设置堆内存为物理内存的 50%,但不超过 30GB。超过 30GB 时,JVM 使用指针压缩会失效,导致性能下降。
磁盘:为了获得较高的 I/O 性能,最好将数据存储在 SSD 上,避免使用传统机械硬盘。
CPU:Elasticsearch 的性能受 CPU 性能影响较大,特别是在处理大规模查询时,选择多核 CPU 会提升性能

2. 集群和节点配置

Elasticsearch 通常部署在多个节点上,以提高数据的冗余性、可用性和查询性能。

主节点 (Master Node):主节点负责集群管理和元数据管理,推荐将主节点与数据节点分开,避免主节点过载。
数据节点 (Data Node):数据节点存储和处理数据。你可以根据需求选择多个数据节点,以分担负载。
客户端节点 (Coordinating Node):客户端节点主要用于路由查询请求到相应的数据节点。通常情况下,你可以直接通过负载均衡的方式访问客户端节点。
合理配置分片和副本:

分片(Shards):数据在 Elasticsearch 中以分片的方式存储,默认情况下每个索引有 5 个主分片。合理的分片数量可以提高查询性能和数据处理效率。过多的分片会带来管理和性能问题,过少的分片会导致数据分布不均,影响性能。
副本(Replicas):副本提供数据的冗余备份,并且可以提高查询的并发性。建议根据需求调整副本数量。副本数越多,查询性能越高,但也会占用更多的存储空间。

3. 索引设计与映射

索引设计不当会影响查询性能和存储效率,因此在设计索引时需要特别注意:

映射(Mapping):映射定义了索引中文档字段的类型(如 text、keyword、date 等),合理的映射可以优化存储和查询性能。避免动态映射生成不必要的字段。
字段类型选择:选择合适的字段类型。例如,text 类型适用于需要分词的字段,keyword 类型适用于精确匹配的字段,date 类型适用于时间相关字段。
避免过多的字段:尽量避免不必要的字段,避免大量使用 nested 类型和 object 类型,因为它们会增加查询复杂度。
文档大小:避免单个文档过大,否则会影响性能。将大文档拆分成多个小文档会更有利于性能。

4. 查询性能优化

Elasticsearch 的查询性能直接影响到系统的响应速度和稳定性,以下是一些常见的优化建议:

使用过滤器(Filters)而非查询(Queries):过滤器不会影响评分,因此它们比查询更高效。对于常用的精确匹配条件,使用 filter 代替 query。
避免使用通配符(Wildcard)查询:通配符查询(如 * 和 ?)会非常消耗性能。尽量避免或只在需要时使用。
合理使用分页避免对大量数据进行深度分页查询。深度分页会导致性能问题,因为 Elasticsearch 需要加载大量无用的结果。可以使用 search_after 或 scroll API 来替代。
避免过于复杂的查询:复杂的查询(如嵌套查询、多层聚合)会消耗更多的计算资源。根据业务需求合理简化查询。

5. 监控与日志管理

集群健康监控:定期检查集群健康状态,使用如 /_cluster/health API 查看集群的健康状况。
日志管理:定期检查 Elasticsearch 日志,查看是否有性能瓶颈或错误信息。日志可以帮助你快速发现潜在问题。
使用监控工具:可以使用 Elastic Stack(如 Kibana)监控集群性能,查看节点的资源使用情况和查询执行时间。

6. 数据备份和恢复

快照(Snapshot):定期进行数据快照备份。Elasticsearch 提供了 snapshot 和 restore API 来进行集群的数据备份和恢复。确保配置好快照存储位置(如远程仓库),以防数据丢失。
恢复策略:在恢复时,根据恢复的需求和节点状态合理选择恢复策略,避免造成集群的负载过高。

7. 安全性

Elasticsearch 默认并未启用认证和授权,因此,使用时需要考虑安全性:

启用认证:使用 Elastic Stack 的 X-Pack 或者第三方插件启用身份验证,限制对 Elasticsearch 的访问。
网络安全:通过防火墙、IP 白名单等手段限制访问,确保只有授权的主机或用户能访问 Elasticsearch。
加密通信:启用 TLS/SSL 加密,确保客户端和 Elasticsearch 之间的通信安全。

8. 分布式特性和容错

数据冗余:通过副本(replica)配置实现数据冗余,确保节点故障时数据不丢失。
分布式处理:理解 Elasticsearch 的分布式特性,如何在多个节点间分配分片、处理请求。合理配置节点间的负载均衡,提高系统的容错能力。

9. 升级和兼容性

版本兼容性:升级 Elasticsearch 时,需要注意版本之间的兼容性。新版本可能引入不兼容的变更,因此升级前需进行充分的测试。
升级策略:尽量避免直接在生产环境中进行大规模版本升级。可以先在开发环境中验证新版本的性能和功能,再推送到生产环境。

总结:

使用 Elasticsearch 时,合理的资源配置、索引设计、查询优化、安全管理以及监控维护是确保系统高效、稳定和安全的关键。遵循上述最佳实践,定期进行性能优化和监控,有助于提升 Elasticsearch 集群的可用性和响应速度。


原文地址:https://blog.csdn.net/weixin_44372802/article/details/143619190

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!