2025-12-29一次 Trino 连接 Hive 的“诡异故障”:GMT+08:00 时区引发的 Catalog 初始化失败
0. TL;DR
-
• 环境组合
- • Trino:435
- • JDK:17.0.12
- • CDH:6.3.2
- • Hive:2.1.1(Metastore + HiveServer2)
- • Hive Metastore:
thrift://prd-data:9083 - • HDFS:
fs.defaultFS=hdfs://prd-data:8020 - • 系统时区:GMT+08:00
-
• 现象
- • ClickHouse / MySQL catalog 正常
- • Hive catalog 一直报:
Catalog 'hive' failed to initialize and is disabled - • Trino 启动日志中出现大量
Guice ERROR_INJECTING_CONSTRUCTOR,核心报错为:
The datetime zone id 'GMT+08:00' is not recognised
-
• 根因
- • Trino Hive connector 在初始化 Parquet / RCFile 相关组件时,会从配置中拿一个“时区字符串”给 JodaTime:
DateTimeZone.forID("GMT+08:00") - • JDK 的
GMT+08:00对 Java Time 没问题,但对 Joda Time 来说,这个 ID 不合法,直接抛 IllegalArgumentException,导致 Hive catalog 初始化失败。
- • Trino Hive connector 在初始化 Parquet / RCFile 相关组件时,会从配置中拿一个“时区字符串”给 JodaTime:
-
• 解决方案(关键配置)
在etc/catalog/hive.properties中显式指定 Hive 用到的时间格式时区为 Joda 能识别的 ID,例如:``` connector.name=hive hive.metastore.uri=thrift://prd-data:9083# HDFS 支持(根据自己情况) fs.hadoop.enabled=true hive.config.resources=/etc/hive/conf.cloudera.hive/core-site.xml,/etc/hive/conf.cloudera.hive/hdfs-site.xml
# 关键修复:显式指定时区,绕开 JVM 默认的 GMT+08:00 hive.parquet.time-zone=Asia/Shanghai hive.rcfile.time-zone=Asia/Shanghai hive.orc.time-zone=Asia/Shanghai
1. 背景环境
这次事故的环境大概是这样:
- • 大数据栈:CDH 6.3.2
- • Hive 2.1.1(由 Cloudera Manager 管理)
- • Hive Metastore:
- •
hive.metastore.uris=thrift://prd-data:9083 - • warehouse:
/user/hive/warehouse
- •
- • HDFS:
- •
fs.defaultFS=hdfs://prd-data:8020
- •
- • 查询引擎:Trino 435
- • 单机部署,
/apps/trino/trino-server-435 - • JDK 17 安装在
/apps/trino/jdk_17 - • HTTP 端口:
6868
- • 单机部署,
- • 其他 Catalog:
- • ClickHouse(25.3)通过 jdbc catalog 正常工作
- • MySQL 8(阿里云 RDS)通过 jdbc catalog 正常工作
目标是:
在这台机器上让 Trino 通过 Hive connector 访问 CDH 上的 Hive Metastore + HDFS 数据。
2. 故障现象
Trino 服务启动正常:
systemctl status trino
# Active: active (running)
ClickHouse / MySQL catalog 正常:
SHOW SCHEMAS FROM clickhouse;
SHOW SCHEMAS FROM mysql8;
唯独 Hive:
SHOW SCHEMAS FROM hive;
返回:
Query failed: Catalog 'hive' failed to initialize and is disabled
io.trino.spi.TrinoException: Catalog 'hive' failed to initialize and is disabled
Trino CLI / DBeaver 中行为一致,说明问题不在客户端。
3. 常规排查:确认 Hive 自己没问题
3.1 Metastore 是否正常监听
ss -lntp | grep 9083
# LISTEN 0 50 0.0.0.0:9083 ... java ... HiveMetaStore -p 9083
进程日志:
ps aux | grep HiveMetaStore
# hive ... org.apache.hadoop.hive.metastore.HiveMetaStore -p 9083
Metastore 进程正常。
3.2 配置是否一致
Hive 自己的 hive-site.xml:
<property>
<name>hive.metastore.uris</name>
<value>thrift://prd-data:9083</value>
</property>
Trino 的 hive.properties:
connector.name=hive
hive.metastore.uri=thrift://prd-data:9083
配置一致。
3.3 HDFS 配置文件是否可用
ls -l /etc/hive/conf.cloudera.hive/core-site.xml /etc/hive/conf.cloudera.hive/hdfs-site.xml
# 均存在
core-site.xml 中 fs.defaultFS 指向同一个 HDFS:
<name>fs.defaultFS</name>
<value>hdfs://prd-data:8020</value>
说明 Hive 集群本身是健康的。问题的焦点在 Trino Hive connector 初始化阶段。
4. 关键线索:Guice 报错 + Joda 时区异常
从 server.log 中搜索 Hive 相关错误:
cd /apps/trino/data/var/log
grep -n "Failed to load catalog hive" server.log
# ...
sed -n '上下若干行' server.log
看到核心堆栈:
[Guice/ErrorInjectingConstructor]: IllegalArgumentException: The datetime zone id 'GMT+08:00' is not recognised
at ParquetPageSourceFactory.<init>(ParquetPageSourceFactory.java:135)
while locating ParquetPageSourceFactory
at HiveModule.configure(HiveModule.java:127)
...
Caused by: IllegalArgumentException: The datetime zone id 'GMT+08:00' is not recognised
at org.joda.time.DateTimeZone.forID(DateTimeZone.java:249)
at HiveConfig.getParquetDateTimeZone(HiveConfig.java:716)
...
还有一段类似的:
Caused by: IllegalArgumentException: The datetime zone id 'GMT+08:00' is not recognised
at DateTimeZone.forID(DateTimeZone.java:249)
at HiveConfig.getRcfileDateTimeZone(HiveConfig.java:649)
at RcFilePageSourceFactory.<init>(RcFilePageSourceFactory.java:79)
...
解读:
- • Trino 在初始化
ParquetPageSourceFactory和RcFilePageSourceFactory时,会从HiveConfig拿时间配置; - •
HiveConfig.getParquetDateTimeZone()/getRcfileDateTimeZone()内部调用DateTimeZone.forID()(JodaTime); - • 传入的 zone ID 是
"GMT+08:00"; - • JodaTime 不认这个字符串 → 直接抛 IllegalArgumentException;
- • Guice 构造这些 bean 时失败 → Hive connector 初始化失败 → catalog 被标记为 disabled。
这一点非常关键:
链路从单纯的 Metastore/HDFS 连通性,收敛到了 Hive connector「内部配置解析」这一层。
5. 根因分析:JVM 默认时区 vs Joda 时区 ID
在 Trino Hive connector 中,时间相关的几个配置大致是这样的(精简概念):
- •
hive.parquet.time-zone - •
hive.rcfile.time-zone - •
hive.orc.time-zone
含义:
用于控制读取 ORC/Parquet/RCFile 中时间字段的时区处理。
如果不显式配置,一般会采用 JVM 默认时区。
而在这台机器上,JVM 默认时区是:
GMT+08:00
在 JDK / java.time.ZoneId / TimeZone 的世界里,这种写法是可以接受的;
但是 Trino Hive 使用的是 JodaTime,它要求:
- • 要么是区域名,如
Asia/Shanghai; - • 要么是纯偏移,如
+08:00;
像 "GMT+08:00" 这样的字符串,对 Joda 来说不合法,于是 DateTimeZone.forID("GMT+08:00") 直接抛异常。
因此,虽然我们压根没在 hive.properties 中配置 hive.parquet.time-zone 这些属性,
但默认行为会把 JVM 默认时区字符串“原封不动地当成配置值”传给 JodaTime,最终导致初始化失败。
这就解释了:
- • 为什么 clickhouse / mysql8 完全没事:它们用不到 Joda 的这个路径;
- • 为什么 只要一加载 Hive connector 就报
ERROR_INJECTING_CONSTRUCTOR:
Parquet / RCFile 相关类在构造时就挂掉了。
6. 解决方案:显式指定 Hive 的 time-zone
6.1 在 hive.properties 中设置合理的时区
对本次环境(东八区)来说,推荐设置为 Asia/Shanghai:
connector.name=hive
hive.metastore.uri=thrift://prd-data:9083
# HDFS 支持(按实际情况配置)
fs.hadoop.enabled=true
hive.config.resources=/etc/hive/conf.cloudera.hive/core-site.xml,/etc/hive/conf.cloudera.hive/hdfs-site.xml
# 关键修复:显式设置时间格式时区为 Joda 可识别的 ID
hive.parquet.time-zone=Asia/Shanghai
hive.rcfile.time-zone=Asia/Shanghai
hive.orc.time-zone=Asia/Shanghai
保存之后,重启 Trino:
systemctl restart trino
# 或 /apps/trino/current/bin/launcher restart
然后在 CLI 中验证:
jdk_17/bin/java -jar /apps/trino/trino-cli.jar \
--server http://127.0.0.1:6868 \
--user trino \
--password \
--catalog hive \
--schema default
trino> SHOW SCHEMAS FROM hive;
此时 Hive catalog 能正常列出 schema,问题解决。
备注:如果不想写区域名,也可以用偏移写法:
hive.parquet.time-zone=+08:00等,同样能被 Joda 识别。
6.2(可选)在 JVM 层统一设定时区
为了避免将来有其它地方也踩到 GMT+08:00 这个坑,可以在 jvm.config 中增加:
-Duser.timezone=Asia/Shanghai
结合本次配置,jvm.config 末尾类似:
-Xms4G
-Xmx4G
-DHADOOP_USER_NAME=hive
-Duser.timezone=Asia/Shanghai
这不是必须项,但对整体行为更可控。
7. 额外经验:这次排查顺带踩到的其他点
这次事故除了时区问题,其实还顺手排掉了两个常见坑:
7.1 Trino 开启密码认证必须配 internal-communication.shared-secret
- • 开启密码认证时,我们在
config.properties中加了:``` http-server.authentication.type=PASSWORD http-server.authentication.allow-insecure-over-http=true - • 随后 Trino 启动直接报一堆 Guice 错误,核心提示是:```
Shared secret (internal-communication.shared-secret) is required when authentication is enabled
- • 解决办法:必须追加一行:```
internal-communication.shared-secret=trino-shared-secret-xxxx
这个值随便生成一个足够长的随机字符串即可(集群多节点时需要一致)。
7.2 MySQL catalog 配置不要乱写不存在的属性
- • 一开始 MySQL catalog 写成:```
connector.name=mysql
connection-url=jdbc:mysql://host:3306
connection-user=admin_dev
connection-password=xxx
connection-properties=useUnicode=true&...
- • Trino 的 MySQL connector 没有
connection-properties这个配置项,
导致加载 catalog 时直接抛异常 →Catalog 'mysql8' failed to initialize and is disabled。 - • 正确写法是:所有 JDBC 参数拼到 URL 里:```
connector.name=mysql
connection-url=jdbc:mysql://host:3306?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
connection-user=admin_dev
connection-password=xxx
8. 总结:排查 Trino Catalog 问题的一套套路
这次 Hive 的问题有点“偏门”,但排查过程可以沉淀出一个通用 checklist,供后续参考:
- 1. 先确认 Trino 进程健康
- •
systemctl status trino/launcher status - •
curl http://127.0.0.1:6868/v1/info
- •
- 2. 再确认底层服务健康
- • Hive Metastore:端口 9083 是否 LISTEN、
hive.metastore.uris是否一致; - • HDFS:
fs.defaultFS是否正确; - • MySQL/RDS:本机
mysql -h ...能否连通。
- • Hive Metastore:端口 9083 是否 LISTEN、
- 3. 针对某个 catalog 报
failed to initialize and is disabled时:- • 在
server.log中搜索:- •
Failed to load catalog hive - •
Caused by:
- •
- • 往上/往下看 50~100 行,重点关注:
- • 配置项非法(Unknown configuration property)
- • 网络异常(ConnectException)
- • 类加载错误(ClassNotFound / NoSuchMethod)
- • 这次这种:时区 ID 不被 Joda 识别
- • 在
- 4. 对 Hive 这类复杂 connector,建议从“极简配置”开始:
- • 先只写:```
connector.name=hive
hive.metastore.uri=thrift://host:9083
- • 确认能起,再渐进式加:
- • HDFS 支持(
fs.hadoop.enabled+hive.config.resources) - • 时区相关配置
- • 安全相关配置(Kerberos / Ranger 等)
- • HDFS 支持(
- • 先只写:```
connector.name=hive
hive.metastore.uri=thrift://host:9083
- 5. 遇到 Guice 的
ERROR_INJECTING_CONSTRUCTOR一定不要只看第一行
真正的根因通常在几十行后的 第一个Caused by,这次的GMT+08:00就是典型代表。
.preview-wrapper pre::before { position: absolute; top: 0; right: 0; color: #ccc; text-align: center; font-size: 0.8em; padding: 5px 10px 0; line-height: 15px; height: 15px; font-weight: 600; } .hljs.code__pre > .mac-sign { display: flex; } .code__pre { padding: 0 !important; } .hljs.code__pre code { display: -webkit-box; padding: 0.5em 1em 1em; overflow-x: auto; text-indent: 0; } h2 strong { color: inherit !important; }
本文使用 文章同步助手 同步