ElasticSearch 8.x 版本 Java Client推荐的是 ElasticsearchClient,今天简单尝试了下这个依赖库,将碰到的一些问题进行了简单的整理。
co.elastic.clients
elasticsearch-java
jakarta.json
jakarta.json-api
jakarta.json
jakarta.json-api
2.1.1
io.github.hakky54
sslcontext-kickstart
7.4.6
这里需要注意,jakarta.json-api 不是必需的,只有在出现 ClassNotFoundException: jakarta.json.spi.JsonProvider 的时候才需要引入,而且必须在最顶层的项目中进行引用。
官方给出的解决方案是在 top-level project dependency 中进行引用,这里一定要注意。
sslcontext-kickstart 是为了解决另外一个问题,而且是一个大坑,这个后面再说。
public ElasticsearchClient elasticsearchClient() {
SSLFactory sslFactory = SSLFactory.builder()
.withUnsafeTrustMaterial()
.withUnsafeHostnameVerifier()
.build();
HttpHost httpHost = new HttpHost("localhost", 9200, "https");
//添加认证
final CredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "password"));
RestClientBuilder builder = RestClient.builder(httpHost);
builder.setHttpClientConfigCallback(f ->
f.setDefaultCredentialsProvider(provider)
.setSSLContext(sslFactory.getSslContext())
.setSSLHostnameVerifier(sslFactory.getHostnameVerifier()));
RestClient restClient = builder.build();
//如果由多个es节点,可以采用以下的方式来指定
// RestClient restClient = RestClient.builder(
// new HttpHost("localhost", 9200, "http"),
// new HttpHost("localhost", 9201, "http")).build();
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
return new ElasticsearchClient(transport);
}
如果没有开安全认证,那么可以直接按以下方式来初始化。
// Create the low-level client
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200)).build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
// And create the API client
ElasticsearchClient client = new ElasticsearchClient(transport);
这里是因为我项目中引入了Consul作为注册中心,需要定期向Consul上报服务节点的健康状态,这里不需要检查ElasticSearch的健康状态,所以我直接关掉了。
management:
health:
elasticsearch:
enabled: false
调用 ElasticSearchClient 进行API调用时,总体失败,控制台返回的信息是
elasticsearch-rest-client connection is closed
完整的日志我没有保留,但是最主要的就是每次调用API就会提示连接已关闭。
嗯,看了几个相关的帖子,都没有解决问题,当然这里顺便吐槽一下ElasticSearch官方的文档,有些极具迷惑性,比如这个倒霉蛋兄弟的贴子:
elasticsearch-rest-client-connectionclosedexception-when-calling-performreques
他是参考 _talking_to_elasticsearch 配置的,里面有提到与ElasticSearch集群交互用的是9300端口,然后他就配置成了9300…

实际官方的意思是客户端自己封装了和集群交互的功能,实际的API调用还是用的9200。
看了很多帖子,无法解决之后,我去看了下ElasticService服务端的日志
received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress=/127.0.0.1:9200, remoteAddress=/127.0.0.1:58090}
这不就是SSL的问题吗!!!
这里再次吐槽一下,Java client返回的信息真是一言难尽
然后果断引入了 sslcontext-kickstart并在ElasticSearchClient中加入了SSLFactory的配置,启动,调用,功能正常通过。