了解最新的 Spring Data Elasticsearch 5.0.1 和 Elasticsearch 8.5.3,从正确配置 Elasticsearch Docker 镜像开始。
最近,我写了文章“使用 Spring Data Elasticsearch 4.4 进行分页”,但我们已经有了新的 Spring Data Elasticsearch 5.0 和Spring Boot 3.0 版本。在进行升级时,我们应该考虑几个变化和问题。
本文的目的是强调使用这些技术升级sat-elk项目时的变化:
- 弹簧数据弹性搜索 5.0.1
- 春季启动 3.0.2
- 弹性搜索 8.5.3
主要变化
- Elasticsearch 8.5 默认启用了 SSL。
- Spring Data Elasticsearch 5.0 使用新的 Elasticsearch 客户端库。
- Spring Boot 3.0 从
javax
移至jakarta
package (dependencies)。 SearchHits
行为有点不同。
在本文中,您将了解
- 如何设置 Elasticsearch 8.5.3
- 如何在项目中配置Spring Data Elasticsearch 5.0
- 如何处理升级到最新技术
Elasticsearch
我们的目标是有一个应用程序通过 Elasticsearch 中的 Spring Data Elasticsearch 来管理数据。您可以在我最初的文章“ Spring Data Elasticsearch 4.1 简介”中找到更多详细信息。在这里,您只能找到具有突出显示差异或更改的基本步骤。
让我们先检查一下变化。
变化
上一篇文章使用了 4.4 版本的 Spring Data Elasticsearch,但最新版本(在撰写本文时)是 5.0.1 版本。您可以在此处找到所有详细信息。
我们应该牢记包含主要技术兼容版本的兼容性矩阵-> Spring 框架、Spring Boot、Spring Data Release Train、Spring Data Elasticsearch,当然还有 Elasticsearch 本身。
我们的版本由 Spring Boot 3.0.2 和 Spring Data Release Train 2022.0.1 驱动。
Docker Setup
elasticsearch
使用的Docker镜像的第一个重大变化 是默认切换到 HTTPS 而不是以前的 HTTP。这些版本中 Elasticsearch 配置(位于文件中)的差异是:/usr/share/elasticsearch/config/elasticsearch.yml
Elasticsearch 7.17.8:
cluster.name: "docker-cluster" network.host: 0.0.0.0 复制代码
Elasticsearch 8.5.3:
cluster.name: "docker-cluster" network.host: 0.0.0.0 # Enable security features xpack.security.enabled: true xpack.security.enrollment.enabled: true # Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents xpack.security.http.ssl: enabled: true keystore.path: certs/http.p12 # Enable encryption and mutual authentication between cluster nodes xpack.security.transport.ssl: enabled: true verification_mode: certificate keystore.path: certs/transport.p12 truststore.path: certs/transport.p12 #----------------------- END SECURITY AUTO CONFIGURATION ------------------------- 复制代码
之前的提示(请参阅我之前文章中的“在 Elasticsearch 中禁用 XPack”部分)现在不起作用,可能是因为它是一种变通方法。因此,我们应该适当地禁用 X-Pack 安全性。
让我们按照以下步骤正确设置 Elasticsearch。
自定义网络
docker network create sat-elk-net 复制代码
Elasticsearch
docker run -d --name sat-elasticsearch --net sat-elk-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" elasticsearch:8.5.3 复制代码
注意:请参阅-e "xpack.security.enabled=false"
用于禁用 HTTPS 的额外参数。
ElasticHQ
docker run -d --name sat-elastichq --net sat-elk-net -p 5000 :5000 elastichq/elasticsearch-hq 复制代码
Spring Data Elasticsearch
可以在此处找到 5.0.x 版的所有升级说明/提示。
Maven 依赖
我们在Maven项目 ( ) 中使用spring-boot-starter-data-elasticsearch
依赖项,如下所示。我们可以在Maven 中央存储库中找到最新的可用版本。pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <version>3.0.2</version> </dependency> 复制代码
此外,我们的代码还依赖于Spring MVC(用于公开 REST 端点)和jackson.dataformat
CSV 模块(用于读取 CSV 文件)。我们应该将它们添加到我们的项目中:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>3.0.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-csv</artifactId> <version>2.14.1</version> </dependency> 复制代码
Elasticsearch client
第二个关键变化(在 Elasticsearch Docker 镜像配置之后)表示 Spring Data Elasticsearch 使用的新 Elasticsearch 客户端。到目前为止,我们使用文件中的配置spring.elasticsearch.uris
,application.properties
但现在不起作用。
我们仍然可以通过小的调整重新使用它:
spring: elasticsearch: rest: uris: oxygen-arnost.ifs.dev.fra.aws.dbgcloud.io:9200 复制代码
注意: 仅删除了领先的协议。
对于新的 Elasticsearch 客户端,我们需要添加一个ElasticsearchClientConfig
类,我们将此配置属性用作:
爪哇
@Configuration public class ElasticsearchClientConfig extends ElasticsearchConfiguration { @Value("${spring.elasticsearch.rest.uris}") String connetionUrl; @Override public ClientConfiguration clientConfiguration() { return ClientConfiguration.builder() .connectedTo(connetionUrl) .build(); } } 复制代码
ElasticsearchClientConfigTest
为了满足Sonar,我们还需要为这个类添加一个测试。
@SpringBootTest class ElasticsearchClientConfigTest { @MockBean CityRepository cityRepository; @Autowired ElasticsearchClientConfig elasticsearchClientConfig; @Test void clientConfiguration() { assertThat(elasticsearchClientConfig.connetionUrl).contains("oxygen-arnost"); } } 复制代码
SearchHitsImpl 更改
在上一篇文章中,有两个与我们使用SearchHits
接口相关的小问题。
SearchHitsImpl 更改接口
从 5.0 版开始,SearchHitsImpl
类的构造函数被扩展了一个新的pointInTimeId
参数。它对我们的实现没有影响,因为它仅用于最终被删除的测试。
更改没有很好地记录,但可以在SearchHits
类中找到定义:
使用时间点进行搜索时,响应包含新的时间点 ID 值。
不为聚合工作 Jackson 转换
从 Spring Data Elasticsearch 5.0.1 开始,SearchHit
实例包含aggregations
属性 filled(在之前的版本中为 null)。
查看 Spring Data Elasticsearch 4.4.6 的结果:
以及 Spring Data Elasticsearch 5.0.1。
搜索操作本身工作正常。当我们尝试将SearchHits
结果作为 JSON 直接发送给客户端时,就会出现此问题。Spring 不包含AggregationsContainer
该类的任何转换器并产生此错误:
2023-01-05T08:28:44.707+01:00 ERROR 6656 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.springframework.data.elasticsearch.client.elc.ElasticsearchAggregations]] with root cause com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.data.elasticsearch.client.elc.ElasticsearchAggregations and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.data.elasticsearch.core.SearchHitSupport$SearchPageImpl["searchHits"]->org.springframework.data.elasticsearch.core.SearchHitsImpl["aggregations"]) at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.14.1.jar:2.14.1] at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1306) ~[jackson-databind-2.14.1.jar:2.14.1] at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:408) ~[jackson-databind-2.14.1.jar:2.14.1] at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:53) ~[jackson-databind-2.14.1.jar:2.14.1] at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:30) ~[jackson-databind-2.14.1.jar:2.14.1] ... at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na] 复制代码
因此,我们可以使用分页简化我们的搜索功能:
- 删除and 中的 previous
searchPage
和searchHits
方法。CityController``CityService
- 修改我们的
search
方法CityService
为:
@SuppressWarnings("unchecked") public Page<City> search(String name, String country, String subcountry, Pageable pageable) { return (Page<City>) unwrapSearchHits(searchPageFor(searchHits(name, country, subcountry, pageable), pageable)); } 复制代码
这样我们就可以通过分页实现动态搜索,而无需解决SearchHits
相关问题。
可以在 http://localhost:8080/api/cities?name=be&country=Czech&subcountry=bohemia&size=5&sort=name,asc 上使用以下输出验证新的动态搜索实现:
{ "content": [ { "id": "ePHmOIUBcEaiCL6qmck4", "name": "Benešov", "country": "Czech Republic", "subcountry": "Central Bohemia", "geonameid": 3079508 }, ... ], "pageable": { "sort": { "empty": false, "sorted": true, "unsorted": false }, "offset": 0, "pageSize": 5, "pageNumber": 0, "paged": true, "unpaged": false }, "last": true, "totalElements": 3, "totalPages": 1, "size": 5, "number": 0, "sort": { "empty": false, "sorted": true, "unsorted": false }, "first": true, "numberOfElements": 3, "empty": false } 复制代码
结论
本文介绍了使用 Elasticsearch 8.5.3(在本文发布时)升级到最新的 Spring Data Elasticsearch 5.0.1。我们从正确配置 Elasticsearch Docker 镜像开始。接下来,我们演示了由于新的 Elasticsearch 客户端库而改变的配置。最后,我们总结了我们应用程序中所有需要的修复,以使我们的所有功能再次像以前一样工作。