ES Rest High Level Client 在长时间空闲后会抛出 SocketTimeoutException。

8

RestHighLevelClient用于在Spring Boot应用程序中连接到托管在AWS上的ES 6.4。当应用程序长时间处于空闲状态且请求到达时,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

有什么提示或解决方法吗?


看这里,我觉得你面临的问题和我之前回答的一样。https://dev59.com/Muk5XIcBkEYKwwoY49sn#58769415 - Thomas Falkenberg
5个回答

7

我也尝试将连接/套接字超时设置为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;
            }
        };
    }
 

3
在`RestClientBuilder.createHttpClient()`方法中,套接字超时和连接超时的默认值分别设置为30秒和10秒。
您可以通过实现`RestClientBuilder.RequestConfigCallback`并在`RestHighLevelClient`上调用`setRequestConfigCallback(...)`来覆盖这些默认值。
我们做了类似以下的事情:
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) {
    return builder.setSocketTimeout(socketTimeout); // try to prevent SocketTimeoutException
}

1
这是我解决这个问题的方法:

@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
  • Elasticsearch: 7.7.0

0
 @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)方法即可。


0

它还应通过属性进行配置:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接