升级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
相关产品推荐
相关产品推荐

