背景

跨境电商平台需要在 AWS 上部署搜索服务,原有系统使用 Elasticsearch,现需迁移到 AWS OpenSearch Service。

遇到的问题

  • 版本兼容性:OpenSearch 是 Elasticsearch 7.10.2 的分叉版本
  • Tagline 检查:Elasticsearch 客户端会验证服务器 tagline,OpenSearch 返回不同的标识
  • API 差异:部分查询语法在 OpenSearch 中不支持
  • 认证方式:AWS OpenSearch 使用 IAM 或基本认证

架构图

┌─────────────────────────────────────────────────────────┐
│                    Spring Boot Application              │
│                                                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │         ElasticsearchOperations                  │  │
│  │    (Spring Data Elasticsearch API)               │  │
│  └──────────────────────────────────────────────────┘  │
│                         ↓                                │
│  ┌──────────────────────────────────────────────────┐  │
│  │       RestHighLevelClient (ES 7.10.2)            │  │
│  │         (OpenSearch 兼容层)                       │  │
│  └──────────────────────────────────────────────────┘  │
│                         ↓                                │
│  ┌──────────────────────────────────────────────────┐  │
│  │            RestClient (HTTP)                      │  │
│  │         (Basic Auth + SSL/TLS)                    │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                          ↓
                    HTTPS (443)
                          ↓
┌─────────────────────────────────────────────────────────┐
│              AWS OpenSearch Service                      │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │   Index 1    │  │   Index 2    │  │   Index N    │ │
│  │ product-en   │  │ product-fi   │  │    ...       │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
└─────────────────────────────────────────────────────────┘

配置说明

Maven 依赖配置

<properties>
    <java.version>17</java.version>
    <elasticsearch.version>7.10.2</elasticsearch.version>
</properties>

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Elasticsearch 7.10.2 (OpenSearch 兼容) -->
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>${elasticsearch.version}</version>
    </dependency>

    <!-- Spring Data Elasticsearch -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
    </dependency>
</dependencies>

OpenSearch 配置类

@Configuration
@EnableElasticsearchRepositories
public class ElasticsearchConfig {

    @Value("${spring.elasticsearch.uris}")
    private String elasticsearchUris;

    @Value("${spring.elasticsearch.username}")
    private String username;

    @Value("${spring.elasticsearch.password}")
    private String password;

    @Bean
    @Primary
    public RestHighLevelClient elasticsearchClient() {
        // 解析 URI
        String[] uri = parseUri();
        String host = uri[0];
        int port = Integer.parseInt(uri[1]);

        // 设置认证
        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
                AuthScope.ANY,
                new UsernamePasswordCredentials(username, password)
        );

        // 创建客户端
        RestClientBuilder builder = RestClient.builder(
                new HttpHost(host, port, "https")
        ).setHttpClientConfigCallback(httpClientBuilder ->
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
        );

        return new RestHighLevelClient(builder);
    }

    @Bean
    @Primary
    public ElasticsearchOperations elasticsearchOperations() {
        return new ElasticsearchRestTemplate(elasticsearchClient());
    }
}

核心问题与解决方案

问题 1: Content-Type Header 不支持

错误信息

Content-Type header [application/vnd.elasticsearch+json; compatible-with=8] is not supported

原因:Spring Boot 3.x 使用 Elasticsearch 8.x 客户端,发送的 Content-Type 与 OpenSearch 不兼容。

解决方案:使用 Spring Boot 2.7.18 + Elasticsearch 7.10.2 客户端

问题 2: Invalid or Missing Tagline

错误信息

Invalid or missing tagline [The OpenSearch Project: https://opensearch.org/]

原因:Elasticsearch 7.17+ 客户端会验证服务器 tagline,拒绝 OpenSearch 的标识。

解决方案:使用 Elasticsearch 7.10.2 客户端(OpenSearch 分叉的源版本,不检查 tagline)

问题 3: Exists Query 不支持

错误信息

Cannot run exists query on _field_names

原因:OpenSearch 不支持对 _field_names 字段运行 exists 查询。

解决方案:使用 match_all 查询替代

// ❌ 错误写法
new CriteriaQuery(Criteria.where("*").exists())

// ✅ 正确写法
StringQuery query = new StringQuery("{\"match_all\":{}}");

问题 4: Bean 定义冲突

错误信息

The bean 'platformTransactionManagerCustomizers' could not be registered

原因:Spring Boot 3.x 与旧版本依赖冲突。

解决方案:统一使用 Spring Boot 2.7.18

版本兼容性矩阵

Spring Boot Elasticsearch Client OpenSearch 状态
2.7.18 7.10.2 1.3.x ✅ 推荐
2.7.18 7.10.2 2.x ✅ 推荐
3.x 8.x 2.x ❌ 不兼容
2.7.18 7.17.x 2.x ❌ Tagline 错误

相关链接

Spring Boot + AWS OpenSearch 集成

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐