之前使用的elasticsearch 7.14.2,Springboot版本是2.4.13(这个版本坑比较多,用的人也比较少,找问题真的很痛苦)。
es中间件升级到8.13.3之后,之前的代码在使用保存和编辑之后,es数据里面是都操作成功,但是代码接口却会报错。
at java.util.Objects.requireNonNull(Objects.java:203) ~[na:1.8.0_272] at org.elasticsearch.action.DocWriteResponse.<init>(DocWriteResponse.java:116) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.action.index.IndexResponse.<init>(IndexResponse.java:43) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.action.index.IndexResponse.<init>(IndexResponse.java:28) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.action.index.IndexResponse$Builder.build(IndexResponse.java:96) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.action.index.IndexResponse$Builder.build(IndexResponse.java:93) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.action.bulk.BulkItemResponse.fromXContent(BulkItemResponse.java:148) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.action.bulk.BulkResponse.fromXContent(BulkResponse.java:177) ~[elasticsearch-7.15.2.jar:7.15.2] at org.elasticsearch.client.RestHighLevelClient.parseEntity(RestHighLevelClient.java:2011) ~[elasticsearch-rest-high-level-client-7.15.2.jar:7.15.2] at org.elasticsearch.client.RestHighLevelClient.lambda$performRequestAndParseEntity$8(RestHighLevelClient.java:1673) ~[elasticsearch-rest-high-level-client-7.15.2.jar:7.15.2] at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1749) ~[elasticsearch-rest-high-level-client-7.15.2.jar:7.15.2] ... 14 common frames omitted Caused by: java.io.IOException: Unable to parse response body for Response{requestLine=POST /_bulk?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 200 OK} Caused by: java.lang.NullPointerException: null Caused by: java.lang.RuntimeException: Bulk request failed Caused by: java.io.IOException: Unable to parse response body for Response{requestLine=POST /_bulk?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 200 OK}
这个是请求es返回的数据有异常。也就是说低版本的es和版本的es返回的数据结构是有差别的,所以归根到底就是客户端和服务端的版本不一致。es官方也说了,高版本的es推荐使用java 17之后的版本,springboot推荐使用3.0的。但是不能说升级一个中间件结果把整个系统都升级一遍,所以官方也给出了一个兼容的模式,具体的代码放在下面,尤其是maven的依赖包版本不要错误。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <exclusions> <exclusion> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> </exclusion> <exclusion> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> </exclusion> <exclusion> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>4.4.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.17.4</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>7.17.4</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.17.4</version> </dependency>
import cn.hutool.core.convert.Convert; import org.apache.http.Header; import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.nio.reactor.IOReactorConfig; import org.apache.http.message.BasicHeader; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClientBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.client.ClientConfiguration; import org.springframework.data.elasticsearch.client.RestClients; import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import javax.annotation.PreDestroy; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.util.List; @Configuration public class RestClientConfig extends AbstractElasticsearchConfiguration { @Autowired private ElasticsearchProperties elasticsearchProperties; private RestHighLevelClient client; @Override @Bean public RestHighLevelClient elasticsearchClient() { RestClientBuilder restBuilder = RestClient .builder(this.getHttpHosts()); restBuilder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder .setKeepAliveStrategy(getConnectionKeepAliveStrategy()) .setMaxConnPerRoute(10). setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build())); String username = elasticsearchProperties.getAccount().getUsername(); String password = elasticsearchProperties.getAccount().getPassword(); SSLContextBuilder sscb = SSLContexts.custom(); try { sscb.loadTrustMaterial((chain, authType) -> { // 在这里跳过证书信息校验 //System.out.println("暂时isTrusted|" + authType + "|" + Arrays.toString(chain)); return true; }); } catch (NoSuchAlgorithmException | KeyStoreException e) { e.printStackTrace(); } if (username != null && password != null) { final CredentialsProvider credential = new BasicCredentialsProvider(); credential.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); restBuilder.setHttpClientConfigCallback(httpClientBuilder -> { try { return httpClientBuilder .setSSLContext(sscb.build()) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .setDefaultCredentialsProvider(credential) .setKeepAliveStrategy(getConnectionKeepAliveStrategy()) .setMaxConnPerRoute(10) .setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } catch (KeyManagementException e) { throw new RuntimeException(e); } }); } restBuilder.setDefaultHeaders(compatibilityHeaders()); restBuilder.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(1000) //time until a connection with the server is established. .setSocketTimeout(12 * 1000) //time of inactivity to wait for packets[data] to receive. .setConnectionRequestTimeout(2 * 1000)); //time to fetch a connection from the connection pool 0 for infinite. client = new RestHighLevelClient(restBuilder); restBuilder.build(); RestHighLevelClient esClient = new RestHighLevelClientBuilder(restBuilder.build()) .setApiCompatibilityMode(true) .build(); return esClient; } private Header[] compatibilityHeaders() { return new Header[]{ new BasicHeader(HttpHeaders.ACCEPT, "application/vnd.elasticsearch+json;compatible-with=7"), new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.elasticsearch+json;compatible-with=7") }; } private HttpHost[] getHttpHosts() { List<String> clusterNodes = elasticsearchProperties.getClusterNodes(); HttpHost[] httpHosts = new HttpHost[clusterNodes.size()]; for (int i = 0; i < clusterNodes.size(); i++) { String[] node = clusterNodes.get(i).split(":"); httpHosts[i] = new HttpHost(node[0], Convert.toInt(node[1]), elasticsearchProperties.getSchema()); } return httpHosts; } private ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() { return (response, context) -> 2 * 60 * 1000; } /** * it gets called when bean instance is getting removed from the context if * scope is not a prototype * If there is a method named shutdown or close then spring container will try * to automatically configure them as callback methods when bean is being * destroyed */ @PreDestroy public void clientClose() { try { this.client.close(); } catch (IOException e) { } } @Bean public ElasticsearchRestTemplate restTemplate(RestHighLevelClient restHighLevelClient){ return new ElasticsearchRestTemplate(restHighLevelClient); } }
所以选择中间件升级是一个比较严肃的事情,选择版本要谨慎。
标签:集成,7.15,java,client,SpringBoot2,elasticsearch,org,import From: https://www.cnblogs.com/yangkangIT/p/18460859