【问题标题】:ES Rest High Level Client throws SocketTimeoutException after being idle for sometimeES Rest High Level Client 空闲一段时间后抛出 SocketTimeoutException
【发布时间】:2019-11-10 22:41:06
【问题描述】:

RestHighLevelClient 用于在 spring-boot 应用程序中连接到 ES 6.4(托管在 AWS 上)。当应用闲置一段时间,请求到达时,RestHighLevelClient 会抛出 SocketTimeoutException

[Request processing failed; nested exception is org.springframework.data.elasticsearch.ElasticsearchException: Error while bulk for request: org.elasticsearch.action.bulk.BulkRequest@21511b6c] w
java.net.SocketTimeoutException: 5,000 milliseconds timeout on connection http-outgoing-38 [ACTIVE]
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.timeout(HttpAsyncRequestExecutor.java:387) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.client.InternalIODispatch.onTimeout(InternalIODispatch.java:92) ~[httpasyncclient-4.1.4.jar!/:4.1.4]
at org.apache.http.impl.nio.client.InternalIODispatch.onTimeout(InternalIODispatch.java:39) ~[httpasyncclient-4.1.4.jar!/:4.1.4]
at org.apache.http.impl.nio.reactor.AbstractIODispatch.timeout(AbstractIODispatch.java:175) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.reactor.BaseIOReactor.sessionTimedOut(BaseIOReactor.java:263) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.timeoutCheck(AbstractIOReactor.java:492) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.reactor.BaseIOReactor.validate(BaseIOReactor.java:213) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:280) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591) ~[httpcore-nio-4.4.11.jar!/:4.4.11]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

RestHighLevelClient 是使用以下方法创建的:

    @Bean
    RestHighLevelClient client() {

        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(elasticsearchHostAndPort)
                .build();

        return RestClients.create(clientConfiguration).rest();
    }

使用spring-data-elasticsearch版本3.2.0.M2

任何提示/解决方法?

【问题讨论】:

标签: java spring elasticsearch spring-data-elasticsearch


【解决方案1】:

我还尝试将连接/套接字超时设置为 0,如此处和其他地方所建议的那样。 它最终没有帮助。

spring-data-elasticsearch 建议了另一种解决方案/解决方法 https://jira.spring.io/browse/DATAES-789。 它只是在发生此类异常时执行内部重试。它并不能真正解决问题,但您的客户不会出错。相反,空闲时间后的第一个请求将需要额外的 5 秒(或您配置的任何超时)。

如果您使用 Springboot-data-elasticsearch 4+ 版本(以 Springboot 2.3.0 开始),则可以应用该解决方案。

我可以确认以下解决方案有效(具有我上面提到的限制):


@Configuration
public class ElasticSearchRestClientConfig extends AbstractElasticsearchConfiguration {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public RestHighLevelClient elasticsearchClient() {
        return restHighLevelClient;
    }

    @Bean
    @Override
    public ElasticsearchCustomConversions elasticsearchCustomConversions() {
        return new ElasticsearchCustomConversions();
    }

    @Override
    public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter) {
        return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter) {
            @Override
            public <T> T execute(ClientCallback<T> callback) {
                int retryCount = 0;
                T t = null;
                while (retryCount <= RestClientBuilder.DEFAULT_MAX_CONN_PER_ROUTE && t == null) {
                    try {
                        t = super.execute(callback);
                    } catch (DataAccessResourceFailureException e) {
                        // retry
                        if (e.getCause() != null && (e.getCause().getCause() instanceof SocketTimeoutException) &&
                                (retryCount < RestClientBuilder.DEFAULT_MAX_CONN_PER_ROUTE)) {
                            retryCount++;
                            log.warn("Elasticsearch client - performing retry {} after caught DataAccessResourceFailureException: {}", retryCount, e.getMessage());
                        }
                        else {
                            throw e;
                        }
                    }
                }
                return t;
            }
        };
    }
 

【讨论】:

    【解决方案2】:

    RestClientBuilder.createHttpClient() 中,套接字超时和连接超时的默认值设置为 30 和 10 秒。

    您可以通过实现RestClientBuilder.RequestConfigCallback 并在您的RestHighLevelClient 上调用setRequestConfigCallback(...) 来覆盖此默认值

    我们做了类似的事情

    @Override
    public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) {
        return builder.setSocketTimeout(socketTimeout); // try to prevent SocketTimeoutException
    }
    

    【讨论】:

      【解决方案3】:

      它也应该可以通过属性进行配置:

      spring.elasticsearch.jest.connection-timeout=3000 # Connection timeout in milliseconds.
      spring.elasticsearch.jest.multi-threaded=true # Enable connection requests from multiple execution threads.
      

      【讨论】:

        【解决方案4】:

        我是这样解决这个问题的:

        @Configuration
        @EnableElasticsearchRepositories(basePackages = "com.hamdos.repositories.es")
        @ComponentScan(basePackages = { "com.hamdos.services.es" })
        @Order(2)
        public class Config {
        
            @Bean
            RestHighLevelClient client() {
        
                RestClientBuilder builder = RestClient.builder(
                        new HttpHost("localhost", 9289))
                        .setRequestConfigCallback(
                                new RestClientBuilder.RequestConfigCallback() {
                                    @Override
                                    public RequestConfig.Builder customizeRequestConfig(
                                            RequestConfig.Builder requestConfigBuilder) {
                                        return requestConfigBuilder
                                                .setConnectTimeout(5000)
                                                .setSocketTimeout(60000);
                                    }
                                });
        
                return new RestHighLevelClient(builder);
            }
        
            @Bean
            public ElasticsearchOperations elasticsearchTemplate() {
                return new ElasticsearchRestTemplate(client());
            }
        }
        

        系统信息:

        • spring-data-elasticsearch: 4.0.0.RELEASE
        • spring-boot: 2.3.0.RELEASE
        • 弹性搜索:7.7.0

        【讨论】:

          【解决方案5】:
           @Bean
          override fun elasticsearchClient(): RestHighLevelClient {
              val clientConfiguration = ClientConfiguration
                  .builder()
                  .connectedTo("localhost:9200")
                  .withSocketTimeout(enter time in millisecond)
                  .build()`enter code here`
              return RestClients.create(clientConfiguration).rest()
          }
          

          只需使用 withSocketTimeout(30000) 方法,如上所示

          【讨论】:

            猜你喜欢
            • 2018-06-22
            • 2023-04-04
            • 2019-07-12
            • 2020-10-04
            • 1970-01-01
            • 1970-01-01
            • 2021-11-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多