考古|ES 5.1 的别名名字开始校验,下划线开头等老写法会被拒

举报
岳涛 发表于 2026/11/11 08:38:23 2026/11/11
【摘要】 5.1 的 breaking 只有两条:索引别名开始校验命名规则(空格、不能以 /-/+ 开头、长度上限)……

5.1 的 breaking 只有两条:索引别名开始校验命名规则(空格、不能以 _/-/+ 开头、长度上限),以及 Log4j 2.6 升级到 2.7。同一页还有三条属于插件作者的改动(UnicastHostsProvider 改成拉模型、ZenPing 与 MasterElectService 不再可插拔、onModule 不再有实现)。5.1 之外,5.0 已经删掉了 local discovery(discovery.type: local 会启动失败),单节点场景改用 single-node。本文按 v5.6.16 源码把规则的实现位置和报错消息列出来,并标出一处文档与源码不一致的地方。

说明

实测环境:本地起的 Elasticsearch 5.6.16 单节点实例(官方 tar 包直接跑,堆内存 512MB,外挂 JDK 8),curl 连本地 9200 端口。本文「实测」小节的命令和输出都出自这个实例;文档与源码依据仍按 v5.6.16 标签下的 migrate_5_1.asciidoc、MetaDataCreateIndexService.java、Strings.java 引用,哪些是文档写明、哪些是我的推断,正文里逐处标注。

01-migrate_5_1

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

别名开始校验命名

5.1 迁移文档(migrate_5_1.asciidoc 第 4–11 行):

For an index alias, when the index alias is created, get, or deleted, the index alias name will be validated.

三条规则:

They may not contain spaces.

They may not begin with _, - or +.

They may not be more than 100 UTF-8 encoded bytes.

这在源码里的位置是 MetaDataCreateIndexService.validateIndexOrAliasName:索引名和别名共用这一套校验,只是在校验之后索引名额外加了一条必须小写。

if (!Strings.validFileName(index)) {
    throw exceptionCtor.apply(index, "must not contain the following characters " + Strings.INVALID_FILENAME_CHARS);
}
if (index.contains("#")) {
    throw exceptionCtor.apply(index, "must not contain '#'");
}
if (index.charAt(0) == '_' || index.charAt(0) == '-' || index.charAt(0) == '+') {
    throw exceptionCtor.apply(index, "must not start with '_', '-', or '+'" );
}

Strings.INVALID_FILENAME_CHARS 是 \、/、*、?、"、<、>、|、空格、逗号。所以"不能含空格"只是这组禁用字符里的一项,实际禁用范围更大。

别名那条分支在 AliasValidator.validateAliasStandalone 第 104–112 行,调用的是同一个 validateIndexOrAliasName,异常类型是 InvalidAliasNameException。

还有一处文档和源码不一致的地方要留意。迁移文档写 100 UTF-8 字节,而 v5.6.16 里 MAX_INDEX_NAME_BYTES 是 255(第 108 行),索引名和别名都用这个值。也就是说,按 5.1 文档写的 100 字节在 5.6 的代码里已经不是上限了。本文没有逐个版本核对这个数字是什么时候改的,落地时以你所用版本的行为为准;要保险就按 100 字节设计,两个版本都合规。

02-MetaDataCreateIndexService

图 2:官方文件 MetaDataCreateIndexService.java(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 MetaDataCreateIndexService.java

为什么规则长这样

  • 不能含 \、/:名字会作为路径的一部分参与文件系统操作;
  • 不能含 *、?:多索引匹配的通配符;
  • 不能含逗号:多索引列表的分隔符;
  • 不能含 #:注释符;
  • 不能含 "、<、>、|:URL 里的特殊字符;
  • 不能以 _、-、+ 开头:预留给内部设施和表达式(多索引匹配里 - 用来排除);
  • 长度上限:集群状态里每个别名都要记一条,名字越长占的元数据越多,名称解析也越慢。

这些是官方文档点出的两条(空格、首字符、长度)之外,按禁用字符集能推出来的对应关系,官方没有逐字符解释。

03-bootstrap-checks

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

别名不受约束意味着什么

以前别名能含 /、*、空格这些字符。有人会用它们构造带结构信息的名字,比如:

{ "actions": [ { "add": { "index": "logs-2016", "alias": "logs/2016" } } ] }

5.1 起这类名字会报 InvalidAliasNameException。

宽松期积累下来的问题不止一个名字不能用:这些别名在多索引匹配里会被引擎当成通配符解析、在 URL 里需要额外转义、在 _cat/aliases 的输出里因为含空格而难以按列切分。校验把这些问题挡在创建阶段。

日志和监控是这类改动的实际排查手段:这类错误在节点日志里能直接看到 InvalidAliasNameException 和具体原因(含了哪个字符、超了多少字节)。

# 从日志里找被拒的别名
grep -i "InvalidAliasNameException" /var/log/elasticsearch/elasticsearch.log | head -20

# 从代码和脚本里找可能违规的别名
grep -rnE '"alias"\s*:\s*"[^"]*[ \/*?,"<>|#][^"]*"' --include=*.json --include=*.sh --include=*.py . | head -20

第二条是文本匹配,命中后要人看上下文;它只能提供线索,不能当判定标准——最终以创建时是否报错为准。

按命名空间收敛

官方给了方向:

Aliases can be namespaced using dots. For example, logs.2016.01.

用点号分层。好处是:

  • 和已有的索引命名习惯一致,读写两侧不用切换心智;
  • 点号在大多数工具里不需要转义,_cat/aliases 的输出能按列切分;
  • 分层语义明确,logs.2016.01 一眼能看出是 logs 下 2016 年 1 月。

迁移时建新旧对照:老别名 logs/2016 对应新别名 logs.2016,改动点集中在创建别名的地方,别名引用处(查询、写入)跟着改。

如果某些外部系统的别名改动不了(老系统写死了名字),那就不能升到 5.1。这不是能绕过去的限制,校验在建别名时强制。

Log4j 2.6 → 2.7

The bundled Log4j 2.6 and 2.6.1 versions have been updated to Log4j 2.7, in order to fix problems in passing markers to slf4j.

升级 Log4j 是为了修 markers 传给 slf4j 的问题。默认启动的集群不用管;自定义的日志配置(尤其是自己引了 Log4j 依赖的)要确认和目标版本匹配,本文没有逐个版本核对配置文件的兼容性细节。

同一页里三条插件作者的改动

这几条原文没写,属于 5.1 迁移文档同一页(第 20–39 行):

  • UnicastHostsProvider 改成拉模型:插件不再通过回调推主机列表,改由 ES 主动调用 buildDynamicHosts 拉取,这样能配合 dynamic_hosts 设置,也能让提供者用上 ES 自身的服务(如 NodeService);
  • ZenPing 与 MasterElectService 不再可插拔:在标准进程内运行 ES 时这两个不能换实现,官方保留 Ping#isClosed 以便第三方实现继续工作;如果插件要替换它们,需要自带 Discovery 模块;
  • onModule 不再有实现:所有模块改由 plugin 接口实现,插件里不能再写 onModule(SomeModule)。

第三条和 5.0 那批 onModule → XxxPlugin 的替换是同一件事的收尾。

local discovery 的删除在 5.0

原文把它放在 5.1 里,实际是 5.0 迁移文档(第 39 行)的说法:

Local discovery was removed in favour of running the embedded transport client. […] This means that setting discovery.type to local will fail on startup.

local 类型的作用是:在同一个 JVM 里跑多个节点,以同一个 JVM 通信,省一层网络。5.0 删除,官方给出的替代是"跑内嵌的 transport client"。

v5.6.16 里注册的 discovery 类型有 single-node 等(DiscoveryModule 第 84–86 行),没有 local,所以配了 discovery.type: local 会因为找不到这个类型而启动失败。

单节点场景用 single-node:节点自选为 master,且不会加入任何其它节点的集群(bootstrap-checks.asciidoc 第 47–51 行)。它是给"需要把 transport 绑到外部接口、用 transport client 测试"这类场景准备的。

如果原来是"同一 JVM 多节点"的用法(典型是单元测试),替代方案是内嵌 transport client:用 PreBuiltTransportClient 在测试里连一个真实节点,而不是在 JVM 内起多个节点。

升级检查清单

  1. 列出所有别名,找出含空格、\、/、*、?、"、<、>、|、逗号、#,或以 _、-、+ 开头的:
curl -s 'localhost:9200/_cat/aliases?v'
  1. 给它们定新的点号分层名字,建新旧对照表;
  2. 改创建别名的代码,同时改所有引用处(查询、写入、模板里的 aliases 定义);
  3. 外部系统写死的老别名,联系对方改,或者停在 5.0;
  4. 确认自定义日志配置与目标 Log4j 版本匹配;
  5. 自研插件按上面三条改(buildDynamicHosts、不再替换 ZenPing/MasterElectService、onModule 去掉);
  6. discovery.type: local 改掉:单节点用 single-node,同 JVM 多节点的测试改用内嵌 transport client。

下划线开头的别名还能建吗

alias-name

图 4:本地 5.6.16 单节点实例上的实测输出。上:普通名字照常建;下:下划线开头被拒

curl -s -X PUT "" \
  | jq -r '.error.reason'

Invalid alias name [_foo]: must not start with '_', '-', or '+',HTTP 400。

这条在迁移里容易被忽略,因为 _ 开头的名字在旧版本是合法的,而报错只在建别名的那一刻发生。索引模板和滚动别名如果是脚本批量建的,升级后第一次执行会整批失败 —— 建议在升级前先把现有别名名字过一遍,别等执行时才发现。

写在最后

5.1 的 breaking 只有两条,别名校验和 Log4j 升级。别名这条的影响面比它看起来大:它给以前完全不受约束的别名补上了和索引名同级的校验,[“”“']加了几个字符的限制[“””']只是表象。

我的默认做法是:排查这类问题先看日志,它会明确指出原因(含了哪个字符、超了多长),比翻代码快。改的时候用点号分层,和索引命名保持一致。

另外记住:别名的长度上限在不同版本里不一样(5.1 文档写 100 字节,5.6.16 的源码里是 255)。别把名字设计到贴近上限,留余量比记版本号可靠。

参考

本文对照 Elasticsearch v5.6.16 标签的官方文档核对,引文逐字取自原文;文中「实测」小节的命令与输出来自本地 5.6.16 单节点实例,不含性能对比。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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