当前位置: 首页 > 知识库问答 >
问题:

2.1.6 spring boot-Elasticsearch Healthcheck失败

杨飞
2023-03-14

***更新-我发现了一个有用的StackOverflow帖子,其中其他人也有类似的问题:Elasticsearch springboot弹性搜索健康管理的Healthcheck监视器失败:ConnectException:Connection Referend

Healthcheck执行器似乎使用了Rest客户机,然而,用于映射、获取索引等的Elasticsearch使用了RestHighLevelClient。我们有一个@config文件,其中包含esPort、esHost和esSchema(即端口9200、主机localhost和模式http)的变量,下面是代码,下面是“esclient.java”类的代码:

ESClientConfig.java类

package com.cat.digital.globalsearch.configuration;

        import com.cat.digital.globalsearch.component.ESClient;
        import org.apache.http.HttpHost;
        import org.springframework.beans.factory.annotation.Value;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;

@Configuration
public class ESClientConfig {

    @Value("${elasticSearch.host}")
    private String esHost;

    @Value("${elasticSearch.port}")
    private int esPort;

    @Value("${elasticSearch.scheme}")
    private String esScheme;

    @Bean
    public ESClient esClient() {
        return new ESClient( new HttpHost(esHost, esPort, esScheme));
    }
}

esclient.java类

package com.cat.digital.globalsearch.component;

import com.cat.digital.globalsearch.model.IndexDocument;
import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.PutMappingRequest;

import java.io.IOException;
import java.util.List;

import static org.elasticsearch.client.RequestOptions.DEFAULT;
import static org.elasticsearch.common.xcontent.XContentType.JSON;

/**
 * Wrapper around {@link RestHighLevelClient}
 */
public class ESClient {

    private final RestClientBuilder builder;
    private final RestHighLevelClient searchClient;

    public ESClient(HttpHost... hosts) {
        this.builder = RestClient.builder(hosts);
        searchClient = new RestHighLevelClient(RestClient.builder(hosts));
    }

/**
     * @param index String represents index name in ES
     * @return true if index exists, false if not
     */
    public boolean hasIndex(String index) throws IOException {
        final GetIndexRequest request = new GetIndexRequest(index);
        try (RestHighLevelClient client = new RestHighLevelClient(builder)) {
            return client.indices().exists(request, DEFAULT);
        }
    }

所以现在我认为对Elasticsearch的“Connection referend”可能是因为在Dev环境中,它试图使用Rest客户端,而连接的正确参数不存在。但这又如何解释Healthcheck监控器在本地的良好工作呢?RestHighLevelClient是否在本地使用?

我在spring boot GitHub的一个问题上发了帖子,并被提到这里。我会尽量让这件事变得简单,这样我就能得到一些帮助。其实很简单。

DR

>

  • 使用spring boot执行器为Elasticsearch服务创建自定义Healthcheck监视器

    创建了1个名为“IndexExists”的自定义Java类(代码如下)

    添加了application.yml文件:rest.uri=['our-dev-url-on-aws']属性

    我有一个应用程序在本地和远程都运行良好,但是当使用spring boot添加一个自定义Healthcheck监视器来监视我的Elasticsearch服务时,我得到一个“连接拒绝”到Elasticsearch并且Healthcheck监视器最终失败。我们在AWS上的负载均衡器尝试命中这个endpoint,因为它返回一个状态:“down”,因为healthcheck无法连接到Elasticsearch,所以负载均衡器开始创建一个新的容器。当查看CloudWatch日志时,这种情况会在无限循环中反复发生(负载平衡器试图生成更多容器)。我想补充一点,这在本地工作得非常好--也就是说,当添加healthcheck监视器,并通过POSTMAN在执行器/健康endpoint上使用HTTP GET请求时,我会得到正确的JSON响应,它是:

    来自/acture/healthendpoint的本地JSON响应(GET请求)

    {
        "status": "UP",
        "details": {
            "indexExists": {
                "status": "UP",
                "details": {
                    "index": "exists",
                    "value": "assets"
                }
            },
            "diskSpace": {
                "status": "UP",
                "details": {
                    "total": 250790436864,
                    "free": 194987540480,
                    "threshold": 10485760
                }
            },
            "elasticsearchRest": {
                "status": "UP",
                "details": {
                    "cluster_name": "elasticsearch",
                    "status": "yellow",
                    "timed_out": false,
                    "number_of_nodes": 1,
                    "number_of_data_nodes": 1,
                    "active_primary_shards": 7,
                    "active_shards": 7,
                    "relocating_shards": 0,
                    "initializing_shards": 0,
                    "unassigned_shards": 5,
                    "delayed_unassigned_shards": 0,
                    "number_of_pending_tasks": 0,
                    "number_of_in_flight_fetch": 0,
                    "task_max_waiting_in_queue_millis": 0,
                    "active_shards_percent_as_number": 58.333333333333336
                }
            }
        }
    }
    

    如您所见,Healthcheck监视器返回顶部的“Details”:{“IndexExists”:等...}部分,该部分检查我的Elasticsearch索引是否映射到string=“Assets”。如果是,则返回“状态”:“up”。

    然而,当将此代码推送到Azure中的构建管道中,以便我可以在dev环境中进行测试时,这是我得到的JSON响应:

    来自/acture/healthendpoint的DEV JSON响应(GET请求)

    {
        "status": "DOWN",
        "details": {
            "indexExists": {
                "status": "UP",
                "details": {
                    "index": "exists",
                    "value": "assets"
                }
            },
            "diskSpace": {
                "status": "UP",
                "details": {
                    "total": 16776032256,
                    "free": 9712218112,
                    "threshold": 10485760
                }
            },
            "elasticsearchRest": {
                "status": "DOWN",
                "details": {
                   "error": "java.net.ConnectException: Connection refused"
                }
            }
        }
    }
    

    我创建并添加到代码库中的Java类是indexexists.java。它实现了HealthIndicator()接口,并使用了来自spring boot的执行器:

    IndexExists.java类

    package com.cat.digital.globalsearch.component;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.actuate.health.Health;
    import org.springframework.boot.actuate.health.HealthIndicator;
    import org.springframework.stereotype.Component;
    import com.cat.digital.globalsearch.data.Indices;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    
    @Component
    public class IndexExists implements HealthIndicator {
        private final ESClient esClient;
        private static final Logger LOGGER = LoggerFactory.getLogger(IndexExists.class);
        Map<String,String> map = new HashMap<>();
    
    
        @Autowired
        public IndexExists(ESClient esClient) {
            this.esClient = esClient;
        }
    
        @Override
        public Health health() {
            try {
                if (!esClient.hasIndex(Indices.INDEX_ASSETS)) {
                    return Health.down().withDetail("index", Indices.INDEX_ASSETS + " index does not exist").build();
                }
            } catch (IOException e) {
                LOGGER.error("Error checking if Elasticsearch index {} exists , with exception", Indices.INDEX_ASSETS,  e);
            }
            map.put("index","exists");
            map.put("value", Indices.INDEX_ASSETS);
            return Health.up().withDetails(map).build();
        }
    }
    

    我不会发布application.yml的所有代码,但这里是我添加的比特。对于spring开发人员配置文件,我只添加了rest uri,其余代码已经在那里了:

    management:
      endpoint:
        health:
          show-details: always
    
    spring:
      profiles: dev
    elasticSearch:
      host: "aws-dev-url"
      port: -1
      scheme: https
      rest:
      uris: ["aws-dev-url"]
    

    我希望这些信息不是太多!我真的需要帮助...如果有人需要更多的信息,请告诉我。谢谢.

  • 共有1个答案

    尚声
    2023-03-14

    看看你的配置,似乎你的应用程序在使用spring数据ElasticSearch。这允许spring数据存储库由Elasticsearch索引支持,您还可以获得ElasticSearchRestTemplate(参见参考文档)。这是应用程序将用于存储库的内容。

    另一方面,spring boot提供的健康指示器(在其他环境中失败的指示器)使用的是org.elasticsearch.client.RestClient。您的自定义健康指示器(在同一环境中正常工作)似乎使用了不同的东西,即esclient。可能这个客户端配置了不同的凭据/URI?

    您似乎没有在application.yml文件中使用正确的配置名称空间;spring.data.elasticsearch.host不存在。请参阅参考文档。您可以在文档中看到配置属性的完整列表,或者可以直接使用支持属性自动完成的IDE(很多都是这样)。

    如果一切都检查出来了,但仍然失败,我会尝试直接调用另一个环境中的elasticsearch实例,例如使用curl命令,以确保该实例允许spring boot正在使用的健康检查请求。类似于:

    curl http://<host-in-other-env>:<port>/_cluster/health/<your-index>
    

    编辑:

    在配置文件中进行了最近的编辑之后,您的应用程序似乎没有使用Elasticsearch REST自动配置。现在可以使用以下内容编辑application.yml文件:

    spring:
      elasticsearch:
        rest:
          uris: ["aws-dev-url"]
    

    这样,我认为您的esclient可以直接注入一个resthighlevelclient,因为spring boot已经创建了一个。

    tldr:运行状况指示器在本地工作,因为它使用默认的“localhost:9200”地址,但在dev中不工作,因为它仍然依赖相同的默认值。使用正确的配置属性和使用spring boot支持应该会使事情变得更容易。

     类似资料:
    • 我尝试运行这个gradle任务(通过gradlew) 它使用cucmber jvm 并收到此错误 当我从cmd中的同一路径运行同一行时: 更新1: 这个cmd在shell控制台中工作: ./构建/发行版/WebLarge测试/bin/WebLargeTests-f html:构建/报告/cucumber/-f json:构建/报告/cucumber/report.json--胶水com.waze.

    • 在两台不同的笔记本电脑上使用maven构建相同的项目。一个是运行良好,一个是显示错误。 状态:两个系统的配置相同。 使用的命令:mvn clean install-DskipTests=true 错误: 我什至尝试删除所有内容,例如再次创建. m2文件夹。

    • 问题内容: 我的程序使用该类(系统偏好设置,而不是用户)将加密的产品密钥数据保存到计算机。问题是,在Windows和Linux上(尚未在OSX上进行测试,但可能是相同的),如果我不使用具有管理员权限的程序运行该程序,则在尝试读取或读取该程序时,它将发出异常或警告。保存数据。 显然,要求用户以“管理员”权限运行程序是不切实际的。理想情况下,我希望操作系统请求用户许可。 这很愚蠢,并且消除了的一半目的

    • 问题内容: 当我使用getFromLocationName调用时,我得到一个IOException,描述为“ grpc failed”。 运行的代码 错误的控制台输出: Android SDK版本(API级别):25 Android Studio插件是最新的。 提前致谢! 编辑: 问题现在似乎已经解决,这是我的解决方案。 问题答案: 更新: 该问题现在似乎已解决。我不确定问题是否就此解决了,因此,

    • 我写了一个方便的屏幕键盘模块,当我在电脑上编写打算以平板模式运行的程序时,我可以导入和使用它。因为我想在未来的许多程序中导入和使用这个实用程序,我想存储当前鼠标位置和在模块开始时鼠标可见性状态,然后在模块退出时恢复那些条件。mouse.get_pos()命令工作正常,但是.mouse.get_visible()命令失败,返回错误消息:AtiniteError:模块'pygame.mouse'没有属

    • 我正在尝试构建我的Android应用程序与Gradle在控制台。但关于任务“:app:TransformClasseSandResourcesWithProGuardForRelease”的获取以下错误: ./gradlew构建--堆栈跟踪 这是我收到的例外情况:

    • “:App:TransformClassesWithDexForDebug”。>com.android.build.transform.api.transformException:当我在studio项目中添加Facebook最新SDK时 Android Studio TransformException:错误:任务“:app:TransformClassesWithDexForDebug”执行失