问题背景
airflow2.0之后的版本更改了时区问题,更改airflow.cfg文件中的default_timezone 和 default_ui_timezone为Asia/Shanghai后,发现在Airflow Web UI 上已经显示了北京时间,但是对scheduler并不起作用,而且调度不稳定,经常出现不调度的情况
官方说明
默认情况下启用对时区的支持。 Airflow 在内部和数据库中以 UTC 格式存储日期时间信息。它允许您使用与时区相关的计划来运行 DAG。目前,Airflow 不会在用户界面中将它们转换为最终用户的时区。它将始终以 UTC 显示在那里。此外,不会转换运算符中使用的模板。时区信息是公开的,由 DAG 的作者决定如何处理它。
如果您的用户居住在多个时区并且您希望根据每个用户的挂钟显示日期时间信息,这将非常方便。
即使您仅在一个时区运行 Airflow,在您的数据库中以 UTC 格式存储数据仍然是一种很好的做法(在 Airflow 意识到时区之前,这也是推荐的甚至是必需的设置)。主要原因是许多国家使用夏令时(DST),时钟在春季向前移动,在秋季向后移动。如果您在本地时间工作,您每年可能会遇到两次错误,此时发生转换。 (pendulum 和 pytz 文档更详细地讨论了这些问题。)这对于简单的 DAG 可能无关紧要,但如果您从事金融服务行业,例如,您需要满足一天结束的最后期限,这将是一个问题。
定位
官方推荐使用default_timezone为UTC
default_timezone配置有两个作用:
● 为了防止你输入了一些native time,会默认采用这个时区.
● web页面中有个Server显示的时区是根据此配置来的.
即使我们在配置中设置Asia/Shanghai时区,ui界面选择的也是 local +8 时区,但需要注意的是
● airflow的db中存储的仍然是UTC
● 模板中取的时间也是UTC的.
● 代码里取得也是UTC时间
从代码中我们也可以定位到,确实使用的还是UTC时间
优化
airflow 1.9 之前的版本使用本地时区来定义任务开始日期,scheduler_interval 中 crontab 表达式中的定时也是依据本地时区为准,但 airflow 1.9 及后续新版本将默认使用 UTC 时区来确保 airflow 调度的独立性,以避免不同机器使用不同时区导致运行错乱,如果在2.0+还想使用本地时区,除了修改了airflow.cfg文件还需要修改相关代码,这一块安装完必须仔细验证下
1、在airflow家目录下修改airflow.cfg,设置
default_timezone = Asia/Shanghai
2、进入airflow包的安装位置,也就是site-packages的位置,以下修改文件均为相对位置
修改airflow/utils/timezone.py
在 utc = pendulum.timezone(‘UTC’) 这行(第27行)代码下添加
# from airflow import configuration as conf
from airflow.configuration import conf # 最新版
try:
tz = conf.get("core", "default_timezone")
if tz == "system":
utc = pendulum.local_timezone()
else:
utc = pendulum.timezone(tz)
except Exception:
pass
修改utcnow()函数
原代码 result = dt.datetime.utcnow()
修改为 result = dt.datetime.now()
修改airflow/utils/sqlalchemy.py
在utc = pendulum.timezone(‘UTC’) 这行代码下添加
# 修改时区
from airflow.configuration import conf
try:
tz = conf.get("core", "default_timezone")
if tz == "system":
utc = pendulum.local_timezone()
else:
utc = pendulum.timezone(tz)
except Exception:
pass
修改airflow/www/templates/admin/master.html – 2.0.2版没有这个
把var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000);
改为 var UTCseconds = x.getTime();
把代码 "timeFormat":"H:i:s %UTC%",
改为 "timeFormat":"H:i:s",
注释airflow/utils/sqlalchemy.py中的cursor.execute(“SET time_zone = ‘+00:00’”)
最后重启airflow-webserver即可