You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Spring Boot 2.7.5搭配ES 7.17客户端兼容7.10.2遇错求助

问题描述

已将Spring Boot版本升级至2.7.5,并将spring-boot-starter-data-elasticsearch客户端升级至7.17版本。当前使用的Amazon Elasticsearch Service版本为7.10.2,因客观原因暂时无法升级Elasticsearch服务端。

完成代码修改后出现以下错误:

org.elasticsearch.ElasticsearchException: Invalid or missing build flavor [oss]

完整堆栈信息:

at org.elasticsearch.client.RestHighLevelClient.performClientRequest(RestHighLevelClient.java:2701) ~[elasticsearch-rest-high-level-client-7.17.6.jar:7.17.6]
    at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:2171) ~[elasticsearch-rest-high-level-client-7.17.6.jar:7.17.6]
    at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:2137) ~[elasticsearch-rest-high-level-client-7.17.6.jar:7.17.6]
    at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:2105) ~[elasticsearch-rest-high-level-client-7.17.6.jar:7.17.6]
    at org.elasticsearch.client.ClusterClient.health(ClusterClient.java:151) ~[elasticsearch-rest-high-level-client-7.17.6.jar:7.17.6]
    at ai.cyr3con.gargoyl3.api.config.elasticsearch.ElasticsearchClient.health(ElasticsearchClient.java:63) ~[classes/:na]
    at ai.cyr3con.gargoyl3.api.common.elasticsearch.repositories.ClusterManagingElasticsearchRepository.health(ClusterManagingElasticsearchRepository.java:15) ~[classes/:na]
    at ai.cyr3con.gargoyl3.api.common.elasticsearch.repositories.ClusterManagingElasticsearchRepository$$FastClassBySpringCGLIB$$b6605bb6.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.23.jar:5.3.23]
    at ai.cyr3con.gargoyl3.api.common.elasticsearch.repositories.ClusterManagingElasticsearchRepository$$EnhancerBySpringCGLIB$$c638bfde.health(<generated>) ~[classes/:na]
    at ai.cyr3con.gargoyl3.api.config.actuator.AbstractElasticsearchHealthIndicator.doHealthCheck(AbstractElasticsearchHealthIndicator.java:31) ~[classes/:na]
    at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:82) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:94) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:41) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpointSupport.getLoggedHealth(HealthEndpointSupport.java:172) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:145) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateContribution(HealthEndpointSupport.java:156) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:141) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:110) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:81) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:88) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:78) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282) ~[spring-core-5.3.23.jar:5.3.23]
    at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:74) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:122) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:97) ~[spring-boot-actuator-2.7.5.jar:2.7.5]
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809) ~[na:na]
    at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) ~[na:na]
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466) ~[na:na]
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307) ~[na:na]
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1399) ~[na:na]
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:827) ~[na:na]
    at java.base/jdk.internal.reflect.GeneratedMethodAccessor205.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359) ~[na:na]
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[na:na]
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[na:na]
    at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
    at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[na:na]
    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562) ~[na:na]
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796) ~[na:na]
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677) ~[na:na]
    at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

当前POM配置

父依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.5</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

属性配置:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.test.redirectOutputToFile>false</maven.test.redirectOutputToFile>
    <java.version>11</java.version>
    <elasticsearch.version>7.17.6</elasticsearch.version>
</properties>
解决方案

该错误源于Elasticsearch 7.17客户端会验证服务端的build flavor,而Amazon Elasticsearch Service 7.10.2返回的build flavor与客户端预期不匹配。以下是无需升级Elasticsearch服务端的解决办法:

方法1:对齐客户端与服务端版本

Spring Boot 2.7.x兼容Elasticsearch 7.10.x,将elasticsearch.version属性改为与服务端一致的版本:

<properties>
    <!-- 其他属性保持不变 -->
    <elasticsearch.version>7.10.2</elasticsearch.version>
</properties>

此方法既能保留Spring Boot 2.7.5的升级,又能彻底规避版本兼容性问题。

方法2:自定义RestHighLevelClient绕过验证

若必须使用7.17版本客户端,可通过自定义客户端添加响应拦截器,修改服务端返回的build flavor头:

import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.protocol.HttpContext;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;

@Configuration
public class ElasticsearchConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestClientBuilder builder = RestClient.builder(/* 替换为你的ES服务地址 */)
                .setHttpClientConfigCallback(httpClientBuilder -> 
                        httpClientBuilder.addInterceptorLast((HttpResponseInterceptor) (response, context) -> {
                            // 修改响应头,让客户端认为服务端build flavor为oss
                            response.setHeader("X-Elasticsearch-Build-Flavor", "oss");
                        })
                );
        return new RestHighLevelClient(builder);
    }
}

方法3:禁用Actuator的ES健康检查

若错误由Actuator健康检查触发,可临时禁用该指示器:

management.health.elasticsearch.enabled=false

此方法仅规避错误,未解决核心兼容性问题,适合无需ES健康检查的场景。


内容的提问来源于stack exchange,提问作者Denis Kisina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:40:43