5.3 的 breaking 只有三条,都不是"不能用了"而是"提前打招呼,6.0 才移除":日志系统属性从单个
es.logs拆成es.logs.base_path、es.logs.cluster_name、es.logs.node_name;transport.type=netty3和http.type=netty3标记废弃;布尔设置只接受true/"true"/false/"false"。第三条的实际行为值得说清楚:v5.6.16 里yes/no/on/off/1/0仍能用,只是会往 deprecation 日志写一条,真正抛异常的是这几个之外的值。本文按 v5.6.16 源码把这一点和其它两条的落地写法列出来。
说明
实测环境:本地起两个单节点实例——Elasticsearch 5.6.16 与 6.8.23(官方 tar 包直接跑,堆内存 512MB),curl 连本地 9200 端口,两个版本分两次启动;弃用日志读的是实例目录下的 logs/elasticsearch_deprecation.log。图 4、图 5 出自 5.6.16,图 6 出自 6.8.23。
来源和边界先交代:本文的依据出自 v5.6.16 标签下的官方文件(migrate_5_3.asciidoc、Netty4Plugin.java、Netty3Plugin.java),文中引用的原文均来自这些文件。示例取自官方示例;哪些是文档写明、哪些是我的推断,正文里逐处标注。
图 1:官方文件 migrate_5_3.asciidoc(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 migrate_5_3.asciidoc
日志属性拆分
5.3 迁移文档(migrate_5_3.asciidoc 第 9–23 行):
Previously Elasticsearch exposed a single system property (
es.logs) that included the absolute path to the configured logs directory, and the prefix of the filenames used for the various logging files (the main log file, the deprecation log, and the slow logs). This property has been replaced in favor of three properties:
es.logs.base_path:日志目录的绝对路径;es.logs.cluster_name:各类日志文件名的默认前缀;es.logs.node_name:配了node.name时才暴露,可选地用于文件名。
The property
es.logsis deprecated and will be removed in Elasticsearch 6.0.0.
拆分的价值:以前 es.logs 是"路径 + 前缀"的拼接体,想在 log4j2 配置里只用其中一部分做不到。拆开之后可以自由组合,典型用法是多节点共用日志目录、文件名带节点名:
appender.rolling.fileName = ${sys:es.logs.base_path}/${sys:es.logs.cluster_name}_${sys:es.logs.node_name}.log
多节点共用目录时这一条尤其重要:文件名不带节点名会互相覆盖。
迁移动作:自定义 log4j2.properties 的地方把 ${sys:es.logs} 换掉。因为 es.logs 是整体,替换时要判断原配置里实际用到的是哪一部分(路径还是前缀)。
图 2:官方文件 Netty4Plugin.java(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 Netty4Plugin.java
Netty 3 废弃
Usage of Netty 3 for transport (
transport.type=netty3) or HTTP (http.type=netty3) is deprecated and will be removed in Elasticsearch 6.0.0.
5.x 期间两套实现都在:netty4(Netty4Plugin 第 50–51 行)和 netty3(Netty3Plugin 第 49–50 行),transport.type / http.type 可以指定用哪个。5.3 起显式声明 Netty 3 要下线。
处理动作只有一个:配置里写了 transport.type=netty3 或 http.type=netty3 的,去掉(默认走 netty4)。6.0 里这两个值不再存在,留着会导致启动失败。
官方没在这个条目里写切换的背景。Netty 3 停止维护、Netty 4 在内存管理上更好这类说法本文没有引用官方出处,不作为迁移依据——需要了解的话以 Netty 官方的发布说明为准。
图 3:官方文件 Netty3Plugin.java(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 Netty3Plugin.java
实际行为是什么
Usage of any value other than
false,"false",trueand"true"in boolean settings deprecated.
关键词是 deprecated(废弃),不是 removed(移除)。源码里的行为(Setting.java 第 862–870 行):
private static Boolean parseBoolean(String key, String value) {
// let the parser handle all cases for non-proper booleans without a deprecation warning by throwing IAE
boolean booleanValue = Booleans.parseBooleanExact(value);
if (Booleans.isStrictlyBoolean(value) == false) {
DeprecationLogger deprecationLogger = new DeprecationLogger(Loggers.getLogger(Setting.class));
deprecationLogger.deprecated("Expected a boolean [true/false] for setting [{}] but got [{}]", key, value);
}
return booleanValue;
}
拆开看:
Booleans.parseBooleanExact接受的其实是 8 个值(Booleans.java 第 73–84 行,报错消息里写的是true/1/on/yes OR false/0/off/no):on、off、yes、no、1、0都还能解析;isStrictlyBoolean只认"true"和"false"(第 88–90 行),不满足就打一条 deprecation 日志:
Expected a boolean [true/false] for setting [xxx] but got [yyy]
- 这 8 个之外的值直接抛
IllegalArgumentException。
所以在 5.x 上,node.data: 0、http.enabled: no 这类写法仍然生效(解析成 false),只是每次启动往 deprecation 日志写一条;不是在 5.3 就失效。留到 6.0 才是真的拒绝。这一点和"已经不能用了"要区分开。
让布尔解析收紧的理由和 5.0 "所有设置必须已知"一脉相承:宽松解析的问题是静默——enabled: off 到底被当成什么,不同版本、不同入口可能不同,而用户以为自己关掉了某功能。5.3 的做法是先用 deprecation 日志提醒,6.0 再切断。
落地:三条怎么改
# 1) 日志属性:老配置里还有没有单个 es.logs
grep -rn "es\.logs" /etc/elasticsearch/jvm.options /etc/default/elasticsearch 2>/dev/null
# 2) Netty 3:6.0 会直接删除,必须提前去掉
grep -rn "type.*netty3" /etc/elasticsearch/elasticsearch.yml
# 3) 布尔宽松写法
grep -rnE ":\s*(yes|no|on|off|0|1)\s*$" /etc/elasticsearch/elasticsearch.yml
# 4) deprecation 日志汇总(按出现次数排)
grep -ho "\[deprecation[^]]*\].*" /var/log/elasticsearch/*.log 2>/dev/null | sed 's/[0-9]\+/N/g' | sort | uniq -c | sort -rn | head -20
第 3 条把 0/1 也加进来了(它们同样属于非严格布尔写法)。命中的行要看键名:只有真的是 ES 的布尔设置才改,on/off 也可能是某个字段的合法字符串值。另外第 3 条只匹配行尾,写在行中间或带注释的形式要人工看。
第 4 条把数字泛化成 N 再聚合,能把同类消息合并(否则每条时间戳不同,统计不出来)。
deprecation log 是最该被当回事的东西
这三条的共同点是[“”"']官方提前打招呼[“”"'],重点不在改了什么。这类条目最合适的处理工具是 deprecation 日志:它直接告诉你"你正在用的这个东西,下个版本就没了",而且针对的是实际用法,不是迁移文档里泛泛的清单。
排序按两个维度:
- 会不会导致启动失败:会失败的排最前(
netty3这种 6.0 直接删的); - 出现次数:高频的先改,说明用得多。
每个大版本升级前跑一次第 4 条,比读迁移文档高效——迁移文档列的是所有可能的改动,deprecation 日志只列你实际用到的。
这个动作在升级前做的成本,远低于升级后排查:升级后你面对的是"某个功能突然没了",却不知道对应哪条弃用。
升级 5.3 的检查清单
log4j2.properties里${sys:es.logs}换成三个新属性,改完确认日志文件名符合预期(多节点共用目录时靠es.logs.node_name区分);- 配置里去掉
transport.type=netty3/http.type=netty3; - 所有布尔设置改成
true/false字面量(含模板、Ansible / K8s 配置里生成的 YAML); - 重启后翻 deprecation 日志,确认没有新的废弃警告残留,并按上面两个维度排期。
在 5.6.16 和 6.8.23 上各跑一遍
第三条「布尔只认 true/false」最容易被当成文字游戏——反正值还是该意思。实测下来两件事要分开看:写法被废弃(只在弃用日志留一句),值照样生效;到 6.8 才开始直接拒。
图 4:5.6.16 上 read_only 分别写 yes、on、1,三次都回 acknowledged: true;跟着往该索引写一条文档被挡(FORBIDDEN/5/index read-only),说明 yes 是当真解释成了 true;弃用日志里留下三行 Expected a boolean [true/false] ... but got [yes]。本地实测输出。
curl -s -XPUT 'http://localhost:9200/r_yes' \
-H 'Content-Type: application/json' \
-d '{"settings":{"index":{"blocks":{"read_only":"yes"}}}}'
# {"acknowledged":true,"shards_acknowledged":true,"index":"r_yes"}
curl -s -XPUT 'http://localhost:9200/r_yes/doc/1' \
-H 'Content-Type: application/json' -d '{"f":1}'
# blocked by: [FORBIDDEN/5/index read-only (api)];
这一步把「写错」的两种后果区分开了:值是错的写法,行为是对的。如果只看返回码,yes 和 true 一模一样,差别全在日志里。我的默认做法是升级前把 deprecation log 当检查项,grep 'Expected a boolean' 一条命令就能把这类写法全捞出来。
图 5:上:真正抛异常的是 yes/on/1 之外的值,maybe 回 400,错误信息自己列出 true/1/on/yes OR false/0/off/no;下:写规范的 true 回 200,弃用日志行数没变。本地实测输出。
到 6.8 才收紧:
图 6:6.8.23 上同一个 read_only: "yes" 直接 400:Failed to parse value [yes] as only [true] or [false] are allowed.;写 true 照常建起来。本地实测输出。
结论是这条迁移的分界在 6.0,5.x 阶段的信号只有日志一行。逐行检查 yml 里的布尔写法收益有限(大部分配置项根本不接受 yes/on),更省事的做法是先 grep 出所有 : yes、: on 这类可疑行,再对着 deprecation log 复核一遍——日志里出现的才是真被解析成布尔的地方。
边界:
- 图 4、图 5 出自 5.6.16 实例,图 6 出自 6.8.23 实例,都是官方 tar 包起的单节点,
read_only只是拿来做样本的布尔设置; - 日志属性拆分(
es.logs→es.logs.base_path等)和 netty3 废弃没有做运行期对照,前者要改log4j2.properties重启,后者要装 netty3 传输实现。
写在最后
5.3 这三条都是"提前打招呼,6.0 才真移除"。我的判断是:处理它们的最好工具是 deprecation 日志:比读迁移文档准,因为它针对实际用法。
三条各自的要点:日志属性拆分后确认文件名(多节点共用目录要靠 es.logs.node_name 区分);netty3 去掉即可,默认就是 netty4;布尔宽松写法在 5.x 还能用但会记 deprecation 日志,6.0 才真正拒绝——我的建议是排查时别只看主日志,deprecation 日志要专门 grep 一遍。
参考
本文对照 Elasticsearch
v5.6.16标签的官方文档核对,引文逐字取自原文。图 4、图 5 是本地 5.6.16 实例的实测输出,图 6 是 6.8.23 实例的对照输出;日志属性与 netty3 两条未做运行期实测,正文中已标注。
