SpringBoot整合Elasticsearch多集群-如何共用一套DAO

Spring Boot 整合 Elasticsearch 多集群:如何共用一套 DAO?

摘要: 多集群支持不只是创建多个 ElasticsearchClient,还要把 DAO、逻辑索引、查询语义和客户端生命周期连接起来。本文结合 MetaLite EsClientManagerBaseEntityEsDaoEsHelper,拆解集群路由、SQL 风格 Criteria 翻译、批量部分失败和当前连接配置边界。

企业系统经常同时使用多个 ES 集群:业务搜索、日志检索、审计归档各自隔离。如果每个 DAO 都手写客户端创建和 Query DSL,连接配置、认证和异常处理很快会分叉。

MetaLite 将“选哪个集群”和“查哪个索引”拆成两个路由层。

一、集群路由和索引路由不是一回事

DAO 通过 @Dao(dataSourceGroup="...") 声明集群名称,EsClientManager 根据名称取得客户端。

实体通过 @Table 声明逻辑索引,TableRouter 再把逻辑索引转换为实际索引,例如按月路由到 app-log-202608

因此一次查询包含两次选择:

dataSourceGroup → Elasticsearch 集群
logicTable + Query → 物理索引表达式

文章 017 已讨论索引路由;本文关注前一层客户端路由和查询翻译。

二、多集群客户端怎样创建和复用

EsProperties 保存集群列表,每项包含名称、节点、用户名和密码。EsClientManager 使用并发 Map 按名称懒创建:

return clientMap.computeIfAbsent(clusterName, name -> createClient(config));

同一 JVM 中,同名集群只复用一个 ElasticsearchClient。应用关闭时遍历 transport,关闭底层 RestClient 并清空 Map。

懒创建减少未使用连接,但也意味着某个集群配置错误可能在第一次业务请求时才暴露。关键集群应增加启动探测或就绪检查。

三、当前节点配置支持到什么程度

节点字符串按逗号拆分,每个节点必须是 ip:port,协议固定为 HTTP。用户名和密码同时非空时启用 Basic Auth。

当前没有暴露这些配置:

  • HTTPS 和证书信任;
  • 节点 URL 路径;
  • 连接、读取和请求超时;
  • 连接池参数;
  • API Key 等认证方式。

所以“支持多集群”不等于适配所有生产 ES 部署形态。接入托管集群或 TLS 集群前,需要扩展客户端配置。

四、公共 Criteria 如何翻译为 ES 查询

EsHelper 将高频操作符映射到 Bool Query:

  • EQ、范围、IN、非空等进入 filter;
  • NE、NIN 和 IS_NULL 进入 must_not;
  • MATCH、MATCH_PHRASE 进入 must;
  • GEO_DISTANCE 构造地理距离查询;
  • LIKE 根据通配符位置选择 prefix 或 wildcard。

filter 不参与相关性评分,适合精确筛选;全文检索使用 must,保留评分语义。

这体现了公共 Criteria 的原则:统一查询意图,不伪装成 SQL 和 ES 完全等价。

五、LIKE 翻译为什么特别容易误用

abc% 会被翻译为 prefix,其他带 % 的形式转为 wildcard。它们通常作用于未分词的 keyword 字段。

如果字段是 text,分析器已经改变词项;如果使用前置通配符,查询成本也可能明显上升。

因此同一个 like 调用在 MySQL 和 ES 中只能表达“近似包含意图”,性能和匹配结果仍取决于 mapping。

六、字段选择和排序有哪些差异

公共 Query 的 include/exclude 字段会转换为 _source filter,普通排序转换为 field sort,带 GeoPoint 的排序则使用 geo distance sort。

JDBC 的 GroupBy 当前不会在 BaseEntityEsDao 中得到对应实现。公共对象里存在某个属性,不代表每个存储引擎都消费它。

调用方应按 DAO 实现能力使用 Query,不能只根据公共接口推断全部功能。

七、按条件更新为什么使用 Painless

ES 没有关系数据库式 UPDATE ... SET ... WHERE ...updateByCriteria 把 Update 字段转换为参数化 Painless 脚本,再调用 update-by-query。

字段值通过 params 传入,避免直接拼值;字段名则进入脚本源。字段最好来自方法引用或受控元数据,不能接受外部任意字符串。

大范围 update-by-query 还会占用集群资源,生产环境需要限制条件范围、超时和冲突策略。

八、批量成功数可能掩盖部分失败

批量新增和批量更新统计 item.error() == null 的条目数并返回。只要部分成功,方法可能返回一个小于输入数量的数字,而不一定抛出整体异常。

调用方如果忽略返回值,就会把部分失败当成成功。

可靠批量链路应检查:

  • 成功数是否等于输入数;
  • 每个失败项的索引、ID 和原因;
  • 是否允许重试,重试会不会重复写入;
  • 路由到多个索引时如何汇总结果。

九、JacksonJsonpMapper 与应用 FastJson2 不冲突吗

ES Java Client 的 transport 使用 JacksonJsonpMapper,而 Web MVC 使用 FastJson2。它们位于不同协议边界:一个负责 ES 客户端 JSONP 映射,一个负责应用 HTTP 与框架 JSON 工具。

但同一实体经过两套序列化器时,日期、字段忽略和自定义注解可能表现不同。实体模型必须用集成测试验证,不能假设 FastJson2 全局配置会影响 ES 客户端。

十、多集群能力最终要验证什么

一套可运营的多集群 ORM 至少需要证明:

  1. DAO 名称能稳定路由到正确集群;
  2. 逻辑索引与物理索引读写对称;
  3. Criteria 在目标 mapping 上语义正确;
  4. 客户端超时、认证和 TLS 满足部署要求;
  5. 批量部分失败不会被忽略;
  6. 应用关闭时所有客户端都能释放;
  7. 单个集群故障不会被误判为全局成功。

MetaLite 已把客户端路由、索引路由和高频查询翻译串成一条统一 DAO 路径。把未覆盖的连接与失败语义明确出来,才能让“多集群”从配置能力变成生产能力。


框架简介
MetaLite 是面向企业生产环境的新一代 Java 微服务技术底座。系列文章重点分享代码背后的设计思路、技术取舍与工程实践。

源码基线
JDK 21、Spring Boot 3.2.9、Spring Cloud 2023.0.1、Spring Cloud Alibaba 2023.0.1.3,具体组件版本以项目 backend-bom 为准。

作者简介
15 年 Spring 体系企业级开发经验,专注于 Java 微服务架构、工程治理与生产实践。

持续更新
MetaLite 系列内容将持续更新,围绕核心设计、源码链路、技术取舍与生产实践展开。欢迎关注作者,及时获取后续内容。

在线演示
演示地址: https://admin.metalite.top/
演示账号: guess
演示密码: admin@2026

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值