考古|ES 5.6 发了高级 REST 客户端,别急,接口还只覆盖五个

举报
岳涛 发表于 2026/11/15 08:33:36 2026/11/15
【摘要】 5.6 的 breaking 有四条,跨两个方向:客户端侧,Java High Level REST Client 首次发布……

5.6 的 breaking 有四条,跨两个方向:客户端侧,Java High Level REST Client 首次发布,官方明确它要在近期取代 TransportClient;部署与语义侧,RPM/Debian 包给 /etc/elasticsearch 加了 setgid,5.6.6 起 bootstrap checks 对 link-local 地址生效,聚合和脚本里引用父文档从 _parent 改成 _parent#父类型。本文按 v5.6.16 逐条给出官方原文和实现细节,并补上 dev/prod 模式的判定依据。

说明

来源和边界先交代:本文的依据出自 v5.6.16 标签下的官方文件(migrate_5_6.asciidoc、bootstrap-checks.asciidoc、parent-field.asciidoc),文中引用的原文均来自这些文件。示例取自官方示例;哪些是文档写明、哪些是我的推断,正文里逐处标注。

实测环境:本地保留 5.6.16 / 6.8.23 / 7.17.29 / 8.19.8 / 9.4.2 五个 ES 发行包,以及带 v5.6.0 / v5.6.16 / v6.0.0 / v8.9.0 / v8.10.0 等标签的上游源码仓库 elasticsearch/;用 git show 读指定标签的源码、用各发行包自带(或系统)javap 读 jar 里的方法签名。另起 7.17.29 单节点实例(HTTP 9212)装 repository-s3 插件,配两个 client(path_style_access 分别为 true / false)指向本地 mock S3 服务(HTTP 9998,使用可解析域名 127.0.0.1.nip.io,记录请求 Host 与路径),S3 凭据写入 keystore。文末实测小节里的命令与响应均取自本机。

01-migrate_5_6

图 1:官方文件 migrate_5_6.asciidoc(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 migrate_5_6.asciidoc

Java High Level REST Client 来了

5.6 迁移文档(migrate_5_6.asciidoc 第 4–13 行):

Starting from version 5.6.0 a new Java client has been released: the Java High Level REST Client. This official high-level client (named like this to differentiate it from the existing low-level client) for Elasticsearch can be used to execute search, index, delete, update and bulk operations using the same Core Java classes as the TransportClient uses.

This Java High Level REST Client is designed to replace the TransportClient in a near future.

两个要点:

  1. 它复用与 TransportClient 相同的 Core Java 类(查询构建器、聚合构建器等),所以请求构造部分的代码基本能平移——这一点官方明确写了;
  2. 官方从发布第一天就说了它要取代 TransportClient。

我的判断是:值得换的原因在协议层面:transport client 走的是 ES 内部传输协议,客户端与集群的版本耦合紧;REST 客户端走 HTTP,耦合小得多。至于"REST 客户端不要求客户端与集群同版本",本文没有查到 5.x 的官方表述,落地时以你所用版本的客户端文档为准。

02-bootstrap-checks

图 2:官方文件 bootstrap-checks.asciidoc(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 bootstrap-checks.asciidoc

迁移时机怎么判断

5.6 的 HLRC 覆盖的是 search、index、delete、update、bulk 这些操作(上面那段引文列出的就是这些),所以当时并不是"立刻迁"的信号。判断时机有几条标准:

  • 接口覆盖:把你用到的 API 列出来,对照客户端文档看有没有对应方法。缺任何一个,要么等,要么混用——HLRC 底层能拿到 low-level client,没封装的接口可以自己发请求;
  • 版本差:transport client 与集群版本耦合紧。集群升级节奏快、客户端跟不上的,迁移收益大;两边版本长期一致且没有升级计划的,可以缓;
  • 大版本升级的时间点:跨大版本对 transport client 是硬约束。升级在即时,先迁客户端再升集群通常更顺,否则要同时处理"协议不兼容"和"业务代码改动"两件事。

回头看,5.6 阶段合理的选择是:新项目试用,老项目等接口完备后再整体迁。这样一次迁完,比 5.6 迁一半省事。

03-parent-field

图 3:官方文件 parent-field.asciidoc(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 parent-field.asciidoc

/etc/elasticsearch 加 setgid

The RPM and Debian packages now set the setgid flag on /etc/elasticsearch so that any files and subdirectories created under /etc/elasticsearch have the same ownership as /etc/elasticsearch (root:elasticsearch). This is used to ensure that files and subdirectories created under /etc/elasticsearch (e.g., a keystore) are readable by the elasticsearch user.

(第 15–23 行)

解决的问题是:在这个目录下创建的文件(比如 keystore)如果属组不对,elasticsearch 用户读不到,服务起不来或安全功能失效。加了 setgid,新建的文件和子目录自动继承 root:elasticsearch 属组。

这类"属组不对"的排查比较烦:报错信息往往不直接指向权限(可能是"读不到 keystore"“证书加载失败”),出问题的时机通常是改完配置重启,容易被误判成"刚才改的配置有问题",排查时要逐个 ls -l 核对属组。

需要留意用工具写入的情况:tar 解压、cp -a、某些同步工具会保留原属组,setgid 不生效。所以这类操作之后确认一次:

ls -la /etc/elasticsearch/
# 属组应该是 elasticsearch
chgrp -R elasticsearch /etc/elasticsearch/

写进部署脚本比人工检查可靠。

Bootstrap checks 覆盖 link-local 地址

Previously when Elasticsearch was bound to localhost, Elasticsearch would bind to any address on the loopback device. This included link-local addresses on the loopback device such as fe80::1%lo0 on macOS. Starting in 5.6.6, Elasticsearch will now only bind to loopback addresses on the loopback device. Because of the previous behavior, Elasticsearch would skip the bootstrap checks if bound to a link-local address. Now that Elasticsearch no longer binds to such addresses when binding to localhost, the bootstrap checks now apply to link-local addresses.

(第 25–35 行)

因果链是这样:

  1. 以前绑 localhost 会绑到 loopback 设备上的所有地址,包括 macOS 上 fe80::1%lo0 这类 link-local 地址;
  2. ES 有个逻辑:绑到 link-local 地址(意味着本地开发场景)就跳过 bootstrap checks;
  3. 于是 macOS 上"只绑了 localhost"的开发环境,会因为同时绑到 link-local 地址而跳过全部启动检查;
  4. 5.6.6 起绑 localhost 只绑真正的 loopback 地址,于是检查照做。

实际感受:本地开发环境升到 5.6.6 之后可能突然报 heap size、文件描述符之类的启动检查失败——因为以前被跳过了。

这里要分清楚 dev 和 prod 模式。官方的定义是(bootstrap-checks.asciidoc 第 30–42 行):只有节点没有把 transport 绑定到外部接口、并且没在用 single-node discovery 时,才算开发模式;生产模式下这些检查是启动失败,不是警告。所以上面那些"突然报错"是生产模式的行为——如果它对你来说是开发环境,说明 transport 绑到了外部接口。单节点场景可以配 discovery.type: single-node(第 47–48 行)。

_parent → _parent#父类型

Previously in Elasticsearch parent documents could be aggregated on or referenced in a script using _parent. Now in order to reference a parent document in an aggregation or script you must do _parent#my_parent as stated in the mapping a parent field documentation.

(第 37–43 行)

_parent   →   _parent#my_parent_type

parent field 文档给了完整写法(parent-field.asciidoc 第 64、80、88 行):父 join 字段在整个名字(_parent#parent_name)下可以在聚合和脚本里引用。聚合示例:

{
  "aggs": {
    "parents": {
      "terms": { "field": "_parent#my_parent" }
    }
  }
}

脚本里取值:

"source": "doc['_parent#my_parent']"

改名原因和 5.x 一系列"消除歧义"的改动一致:一个索引里可能有多个父子关系(多个类型各自定义 parent),只写 _parent 无法区分指的是哪个父类型。带上类型名后指向明确。

这条与 5.5 把 has_child、has_parent、parent_id、children 移到 parent-join 模块是同一条线——父子关系在 5.x 后期被收敛成一个独立模块,语义和命名都在收紧。

升级 5.6 的检查清单

  1. 评估 Java 客户端路线:新代码可以尝试 HLRC,老代码按上面三条标准排迁移时间;
  2. /etc/elasticsearch 下新建文件确认属组为 root:elasticsearch(用 tar、cp -a 写入的尤其要查);
  3. 升到 5.6.6+ 后,把 bootstrap check 报错当作待办逐项处理;确认 transport 绑到外部接口时是生产模式行为;
  4. 聚合与脚本里 _parent 改成 _parent#父类型;
  5. 用了父子关系的场景确认 parent-join 模块在客户端侧已加载,或改用 PreBuiltTransportClient。

在本地仓库上跑一遍

标题说「接口还只覆盖五个」,把 5.6.0 的 RestHighLevelClient 源码拉出来数一次。

04-hlrc-api-list

图 4:本机源码标签的实测输出。v5.6.0 与 v5.6.16 各有 21 个公开方法,v6.0.0 有 23 个;5.6.0 的同步 API 组是 11 个(bulk / clearScroll / delete / exists / get / index / info / ping / search / searchScroll / update),6.0.0 多出 getLowLevelClient。

P=client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
for t in v5.6.0 v5.6.16 v6.0.0; do printf '%s -> ' "$t"; \
  git -C elasticsearch show "${t}:${P}" | grep -cE '^    public [A-Za-z<].*\('; done
# v5.6.0 -> 21
# v5.6.16 -> 21
# v6.0.0 -> 23
git -C elasticsearch show "v5.6.0:${P}" | grep -E '^    public [A-Za-z<].*\(' \
  | grep -v 'void\|RestHighLevelClient(' \
  | sed -E 's/^    public [A-Za-z<>, ]+ ([a-zA-Z]+)\(.*/\1/' | sort -u | tr '\n' ' '
# bulk clearScroll delete exists get index info ping search searchScroll update
curl -s '' | jq -r '.version.number'
# 9.4.2

图 4 给出一个与标题口径不同的结果:从 v5.6.0 源码数出 21 个公开方法,其中同步入口 11 组,每组还配一个异步版本,再加一个构造器。5.6.0 到 5.6.16 数量没变,6.0.0 才多出 getLowLevelClient。标题里的「五个」可能来自首发公告的另一套口径,本机没能查证;这里按源码实际清单记录,不替标题圆场。其余三条 breaking(RPM/Debian 的 setgid、link-local 的 bootstrap checks、_parent#父类型)本篇未实测。

边界:

  • 图 4 出自本机源码仓库的固定标签,没有 5.6 二进制,也没有调用过这些 API;
  • 「五个」的具体出处未查证,正文其他三条 breaking 未实测;
  • 只数了 RestHighLevelClient 一个类的公开方法,未统计请求/响应类。

写在最后

High Level REST Client 在 5.6 首次发布,官方当场就说明它要取代 TransportClient。回过头看,官方给了很长的过渡期:正式取代发生在之后的版本。

所以 5.6 这个时间点的价值是"信号"而不是"必须动"——它告诉你该开始规划了,而不是马上迁。当时的接口覆盖只到 search、index、delete、update、bulk,我的建议是等到接口完备再整体迁,一次做完比迁一半省事。

同一版里的另外三条都是部署与语义层面的小改动:setgid 解决配置属组、link-local 让开发环境的检查生效、_parent#父类型 消除多父子关系下的歧义。前两条不用改代码,第三条要改聚合和脚本里的字段名。

参考

本文对照 Elasticsearch v5.6.16 标签的官方文档核对,引文逐字取自原文。文末实测小节里已实际从 v5.6.0 / v5.6.16 / v6.0.0 的 RestHighLevelClient 源码数出 21 / 21 / 23 个公开方法,5.6.0 的同步 API 组为 11 个,6.0.0 多出 getLowLevelClient。这一结果与标题「只覆盖五个」的口径不同,本机按源码实际清单记录,「五个」的具体出处未查证;无 5.6 二进制、未调用过这些 API;其余三条 breaking 与请求/响应类未实测。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。