时间整整差了八小时

举报
yd_211440595 发表于 2026/11/04 08:49:58 2026/11/04
【摘要】 任务两点跑、日志记十点,差了整整八小时。元凶是容器默认 UTC 时区。一篇时区翻车实录。

那天上午,同事在群里问我:昨晚那个定时清理任务,是不是出问题了?我说没有啊,日志显示跑成功了。他说:那你看看时间——清理任务配的是凌晨两点跑,日志里写的是上午十点。

我打开日志一看,每一条时间戳都比实际早了……不对,是晚了整整八个小时。凌晨两点的任务,日志记成了上午十点。

但任务确实是凌晨两点跑的,因为业务那边两点之后数据就被清了。

也就是说:任务跑对了,日志记错了。

一通乱查

我自信满满地开始排查。

  • 是不是服务器时间不准?date 看了一下,服务器显示的时间是当前北京时间,对的。
  • 是不是 NTP 没同步、时钟漂移了?timedatectl 看了,NTP 同步正常,没有漂移。
  • 是不是日志框架的配置里时区写死了?翻了一遍配置,没看到时区相关字段。
  • 是不是任务实际跑晚了八小时?我又去翻业务侧的记录,确认任务确实是凌晨两点执行的——业务数据两点之后就被清理了,铁证如山。
  • 是不是日志采集有延迟?日志是应用直接写的本地文件,没有采集链路,不存在延迟。
  • 是不是这台机器的系统时区和服务时区不一致?

最后这一条,我查了好几遍才反应过来。date 显示的是北京时间没错,但我漏看了一个东西——日志框架读的时间,不是系统时间,是 JVM 的时间,而 JVM 默认用的是……UTC。

真相

熟悉容器化部署的人这时候大概要笑出声了。

那台机器上跑的是一个容器化应用。宿主机的时区是 Asia/Shanghai,date 显示北京时间,一切正常。但容器内部默认是 UTC 时区——这是几乎所有基础镜像的默认行为,从 Alpine 到 Debian 到 Ubuntu,清一色 UTC。

应用跑在容器里,JVM 继承容器的时区,也就是 UTC。于是日志框架打印时间戳时,用的是 UTC 时间。北京时间凌晨两点,正好是 UTC 前一天的下午六点——不对,是 UTC 当天的……算了,反正是差了八个小时。日志里记的每一行,都比北京时间晚八小时(或者说,UTC 的"凌晨两点"对应的是北京的"上午十点",方向取决于你怎么算,但差值永远固定:八小时)。

任务在容器里按 UTC 的凌晨两点跑?也不对,任务其实是按宿主机 cron 跑的,宿主机是北京时间两点触发的,触发了容器里的应用,应用用 UTC 打了日志。所以:执行时间对,日志时间错。

解决简单到令人窒息:容器启动时挂一个环境变量 TZ=Asia/Shanghai,或者把宿主机的 /etc/localtime 挂进容器。一行配置的事。

几条血泪教训

折腾半天换来的几句话,送给每一个觉得"时间能有什么坑"的人:

  1. "差八小时"基本就是时区问题,第一时间查时区。 这是中国开发者最经典的时区坑——UTC 和 Asia/Shanghai 差八小时,看到这个差值,别犹豫,直接查时区配置。从服务器时区、应用时区、到容器时区,逐层确认。
  1. 容器默认是 UTC,这不是 bug 是约定。 几乎所有基础镜像出厂都是 UTC 时区,不管你宿主机是哪个时区。容器里的应用读到的"当前时间"是 UTC 时间。部署容器化应用,第一步就该设 TZ 环境变量,或者挂载 /etc/localtime。
  1. 日志时间用 UTC 存、本地时区显示,别混用。 业界最佳实践是日志统一存 UTC 时间戳,展示时再按用户时区转换。最怕的是同一份日志里,有的行用 UTC、有的行用本地时间,排查时能把人逼疯。
  1. "date 对 ≠ 应用时间对"。 date 显示的是系统时钟,应用读的时区可能完全不同——尤其是跑在容器、JVM、Python 里的应用,它们各自有自己的时区上下文。排查时间问题,要查的是"应用看到的时区",不是"系统时间"。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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