У меня есть приложение на основе пружины java, развернутое на tomcat, которое взаимодействует с ElasticSearch с помощью RestClient. Я инициализирую RestClient, как показано ниже:
public RestClient buildRestClient() {
int timeout = 10;
//logger.info("Initiallizing Elasticsearch RestClient");
RestClientBuilder builder = RestClient.builder(new HttpHost(EsPropertyUtils.getEsHostname(), EsPropertyUtils.getEsPort(), EsPropertyUtils.getEsScheme()));
builder.setMaxRetryTimeoutMillis(timeout * 1000);
builder.setFailureListener(new RestClient.FailureListener() {
@Override
public void onFailure(HttpHost host) {
}
});
builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder.setConnectTimeout(timeout * 1000).setSocketTimeout(timeout * 1000)
.setConnectionRequestTimeout(0);
}
});
RestClient restClient = builder.build();
return restClient;
}
А ниже приведен пример инициализации клиента и его последующего использования для вызова домена ES
public AnnotatedList<RecommendedLesson> searchForLessonsByKeywords(final String keywords, final QueryProfile profile,
final SearchCriteria searchCriteria) throws RecommendationServiceException {
LOGGER.debug("Search for lessons by keyword(s): {}", keywords);
final int pageSize = Math.min(this.esHelper.getEsSearchMaxResult(),
searchCriteria.getPageSize() > 0 ? searchCriteria.getPageSize() : this.esHelper.getEsDefaultPageSize());
final int pageNumber = searchCriteria.getPageNumber();
try (final RestClient esClient = this.esHelper.buildRestClient()) {
final HttpEntity entity = new NStringEntity(
buildSimpleQueryForSearch(keywords, profile, pageSize, pageNumber, searchCriteria.getFilters(),
searchCriteria.isLessonsWithoutImagesOnly()),
ContentType.APPLICATION_JSON);
final Response response = esClient.performRequest("POST", ES_RECOMMENDATIONS_SEARCH_URL,
Collections.singletonMap("pretty", "true"), entity);
final String responseBody = EntityUtils.toString(response.getEntity());
return new AnnotatedList.Builder<RecommendedLesson>()
.withList(convertResponseToLesssons(responseBody))
.withAnnotation(Annotations.TOTAL_COUNT, getTotalCountFromResponse(responseBody))
.withAnnotation(Annotations.PAGE_SIZE, pageSize)
.withAnnotation(Annotations.PAGE_NUMBER, pageNumber)
.build();
} catch (final ResponseException e) {
LOGGER.error("Exception happened while querying recommended lessons from Elastic Search.", e);
if (e.getResponse().getStatusLine().getStatusCode() == 400) {
LOGGER.warn("The keywords: '{}' is not a valid estatic query string. Empty list is returned.", keywords);
return new AnnotatedList.Builder<RecommendedLesson>()
.withAnnotation(Annotations.TOTAL_COUNT, 0)
.withAnnotation(Annotations.PAGE_SIZE, pageSize)
.withAnnotation(Annotations.PAGE_NUMBER, pageNumber)
.build();
}
throw new RecommendationServiceException(null, "Failed to querying recommended lessons from Elastic Search", e);
} catch (final IOException e) {
LOGGER.error("Exception happened while querying recommended lessons from Elastic Search.", e);
throw new RecommendationServiceException(null, "Failed to querying recommended lessons from Elastic Search", e);
}
}
Функция searchForLessonsByKeywords: вызывается каждый раз, когда пользователь выполняет поиск в моем приложении. По большей части это работает нормально, но при пиковом использовании на сервере мы начинаем периодически видеть ошибку на сервере ... И это также начинает замедлять работу других частей приложения
2020-03-30 16:42:29,931 ERROR [http-nio-8080-exec-6] c.m.s.r.e.RuntimeExceptionMapper [RuntimeExceptionMapper.java:28] Failed to querying recommended lessons from Elastic Search
com.clx.recommender.service.api_1_0.exception.RecommendationServiceException: Failed to querying recommended lessons from Elastic Search
at com.clx.recommender.service.impl.ElasticSearchRecommendationServiceImpl.searchForLessonsByKeywords(ElasticSearchRecommendationServiceImpl.java:236) ~[clx-recommender-service-0.1.0-SNAPSHOT.jar:na]
at com.clx.service.utils.LessonSearchHelper.lambda$searchForLessons$1(LessonSearchHelper.java:109) ~[classes/:na]
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:1.8.0_92]
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) ~[na:1.8.0_92]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_92]
at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291) ~[na:1.8.0_92]
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731) ~[na:1.8.0_92]
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) ~[na:1.8.0_92]
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) ~[na:1.8.0_92]
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) ~[na:1.8.0_92]
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) ~[na:1.8.0_92]
Caused by: java.io.IOException: listener timeout after waiting for [10000] ms
at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:616) ~[rest-5.0.1.jar:5.0.1]
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:212) ~[rest-5.0.1.jar:5.0.1]
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:184) ~[rest-5.0.1.jar:5.0.1]
at com.clx.recommender.service.impl.ElasticSearchRecommendationServiceImpl.searchForLessonsByKeywords(ElasticSearchRecommendationServiceImpl.java:205)
Я склонен увеличивать MaxRetryTimeout с 10 до 20 секунд, но я не верю, что это решает реальную проблему. Какие-нибудь подсказки / идеи относительно того, что я делаю неправильно? Нужно ли явно закрывать соединение с помощью esClient.close () после получения ответа от ES?