airflow的安装和使用-完全版
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
airflow的安装和使⽤-完全版
之前试⽤了azkaban⼀⼩段时间,虽然上⼿快速⽅便,但是功能还是太简单,不够灵活。
Airflow使⽤代码来管理任务,这样应该是最灵活的,决定试⼀下。
我是python零基础,在使⽤airflow的过程中可谓吃尽了苦头。
好⽍最后实现所有要求,两三周的时间没有⽩费
看完这篇⽂章,可以达到如下⽬标:
1. 安装airflow
2. 如何修改界⾯右上⾓显⽰的时间到当前时区
3. 如何添加任务
4. 调试任务python代码
5. 如何启动spark任务
6. 如何限定任务同时执⾏的个数
7. 如何⼿动触发任务时传⼊参数
8. 如何在airflow界⾯上重新运⾏任务
9. 如何查看任务log及所有任务的运⾏记录
10. 如何在任务失败时发邮件(腾讯企业邮箱)
11. 如何在任务失败时发消息到企业微信
以下过程已经过去了有⼀段时间,当时记录的也不⼀定很全⾯,如果有的不能执⾏,请留⾔告知。
安装airflow
系统:Ubuntu 16
python: 3.7
airflow版本:1.10.10
保持pip3到最新版本
pip3 install --upgrade pip
安装使⽤pip3
切换到root⽤户执⾏:pip3 install apache-airflow
你以为敲完这条命令就可以去把个妹或者撩个汉再回来就装好了,请坐下。
我碰到的错误:
Python.h not found
运⾏
sudo apt-get install python3.7-dev
某些依赖版本不对:
ERROR: pendulum 1.4.4 has requirement python-dateutil<3.0.0.0,>=2.6.0.0, but you'll have python-dateutil 2.4.2 which is incompatible. ERROR: pandas 0.25.3 has requirement python-dateutil>=2.6.1, but you'll have python-dateutil 2.4.2 which is incompatible.
运⾏
pip install python-dateutil --upgrade
哪个包版本不对,更新哪个
数据库使⽤mysql
相信你看这个⽂章的时候应该不会还没有尝试装过airflow,所以airflow.cfg这个⽂件已经有了,在哪也很清楚
修改airflow.cfg:
sql_alchemy_conn = mysql://airflow:password@jjh1810:3306/airflow
使⽤root⽤户连接到mysql:
create user 'airflow'@'%' identified by '123';
grant all privileges on airflow.* to 'airflow'@'%';
flush privileges;
set explicit_defaults_for_timestamp = 1; --这⼀⾏⾄关重要
再使⽤airflow⽤户登录mysql:
create database airflow CHARACTER SET = utf8mb4;
初始化数据库
airflow initdb
这时候会报mysql依赖问题,如:
No module named '_mysql'
安装python的mysql依赖:
这个时候终于可以启动airflow了:
启的时候不要使⽤root⽤户,回到普通⽤户
airflow webserver -p 8080
airflow scheduler
如何修改界⾯右上⾓显⽰的时间到当前时区
相信应该所有⼈都会⼲这个事情:
哟?airflow⾥有个时区的配置,改了应该就好了
default_timezone = Asia/Shanghai
然后去刷⼀下页⾯
还是UTC嘛,这配置骗⼈的吗?
那么看这⼀篇⽂章吧:
这个不仅改掉了界⾯上的时区显⽰,⽽且schedule⾥的时间⼀起改掉了,绝对是居家旅⾏,编码调试必备⽅案。
改的时候注意: python的代码是根据缩进来区别代码块的,所以拷代码的时候⼀定要注意缩进没有问题
如何添加任务
在~/airflow下创建dags⽂件夹,把.py⽂件放⼊即可
airflow启动了⼀个叫 DagFileProcessorManager 的进程来扫描dags⽬录,⼀但有⽂件个数变更,或者内容变更都会很快被检测到这个进程有相应的log⽂件,可以提供⼀些⽂件处理错误信息
调试任务python代码
关闭schedule
这个时候已经开始写任务的python代码了,对于python⼩⽩与刚开始接触airflow的⼩哥或⽼哥来说,简直就是痛不欲⽣
有⼀个配置在调试的时候⽐较实⽤,就是关掉任务的schudle,只有⼿动触发才会执⾏。
把dag的schedule_interval设置为None
schedule_interval=None
python⼩⽩实⽤技巧
还有python代码⾥单引号和双引号是等价的,如果有引号嵌套可以分开使⽤,避免⿇烦的转义,如:
hour = '{{ dag_run.conf["hour"] }}'
Jinja template
反正我第⼀眼看到这个东西,特别是官⽅教程⾥那⼀⼤块的模板⽂本的时候,⼼⾥只有⼀个字: WTF?!
templated_command = """
{% for i in range(5) %}
echo "{{ ds }}"
echo "{{ macros.ds_add(ds, 7)}}"
echo "{{ params.my_param }}"
{% endfor %}
"""
其实也不是很复杂,这个玩意理解了以后还是⽐较⽅便的。
除了在代码中使⽤普通的python变量或者airflow内置变量之外,很多时候在字符串中也需要使⽤airflow的内置变量会⽐较灵活和⽅便,Jinja template提供的就是这个功能。
内置变量说明见:
如何启动spark任务
airflow是很强⼤很灵活的,官⽅提供了功能丰富的各种插件,各种JobOperator。
来,简单好⽤童叟⽆欺的SparkSubmitOperator了解⼀下?
我的需求很简单,可以提交任务到不同的spark集群。
这样就要求不能使⽤机器默认的hadoop和spark环境变量,必须为每个任务指定独⽴的配置⽂件。
不知道是不是有⼤⽜⼀次性成功的,反正我是试了⽆数次,⼀句话在⼼⾥不停的重复:“这什么吊东西!”
⼩可愚钝,google能搜出来的都看过了,怎么都不⾏,死活都不⾏,主要是环境变量不对。
调⽤linux脚本执⾏spark-submit是最灵活⽅便的办法
转念⼀想,还是传统的spark提交⽅式最好⽤啊,就是执⾏sh脚本利⽤spark-submit进⾏提交,这样spark就与airflow⽆关了,⽽且不管是环境变量还是参数配置都最灵活,传⼊参数也很⽅便。
这样只要使⽤普通的BashOperator就可以了,⽽且airflow应该专注如何调度任务,⽽不是还要兼顾任务的配置,就算SparkSubmitOperator 可以⼯作,也是使⽤sh脚本的⽅式更好。
如何限定任务同时执⾏的个数
像spark任务通常使⽤的资源都会⽐较多,如果dag执⾏开始时间到当前时间间隔很长,或是暂停很长时间再开启,那么⼀开启的时候schedule会瞬间创建⼤量任务,提交到默认的pool,这个pool默认的⼤⼩是128。
这样肯定是⼤家不希望看到的。
⼀个解决办法,为每个spark任务创建单独的pool,⼤⼩设置为1,这样⼀个spark任务⼀次就只能有⼀个在运⾏状态,后⾯都排队。
界⾯上操作:[Admin] -> [Pools],slots设为1。
然后在spark task的operator⾥添加参数:pool='PoolName'
如何⼿动触发任务时传⼊参数
假设任务是每⼩时触发⼀次,处理24⼩时前的数据,也就是今天8点处理昨天8点这⼀个⼩时的数据。
除了schedule⾃动执⾏的逻辑,我们还希望可以⼿动触发任务,并且指定某个⼩时重新处理。
注:这个功能只有1.10.10才⽀持,就是在界⾯上点击 [Trigger DAG] 的时候可以填⼊参数(固定为Json格式)。
先来看⼀下最终的结果
hour='{{ dag_run.conf["hour"] if dag_run.conf["hour"] else (execution_date - macros.timedelta(hours=24)).strftime("%Y%m%d%H") }}'
这⾥使⽤了Jinja template,通过dag_run对象可以获取界⾯上传⼊的参数,如果没有这个参数(也就是通过schedule触发),那么执⾏默认的逻辑(这⾥是24之前),并且格式化时间与界⾯输⼊保持⼀致。
如何在airflow界⾯上重新运⾏任务
这个功能默认的Executor是不⽀持的,需要安装CeleryExecutor,⽽CeleryExecutor需要⼀个存放消息的框架,这⾥我们选择rabbitmq。
假定rabbitmq已经装好。
安装请看官⽅⽂档:
配置
executor = CeleryExecutor
borker_url = amqp://user:password@host:port
注:如果rabbitmq是集群模式,这⾥也是挑⼀台出来使⽤。
指定所有节点我还没有配置成功,如果有会配置的,请留⾔告知。
如何在界⾯上重跑任务呢?
界⾯上点击dag进⼊dag管理界⾯,点击[Tree View]。
Task每次运⾏都会⽤⼀个⼩⽅块来表⽰,点击⼩⽅块,再点击 [Run] 按钮就可以了。
注: Tree View 这⾥最多只显⽰固定数量的历史记录,如果再早的时间只能通过点击 [Trigger DAG] 再指定参数运⾏。
任务运⾏时间的问题
这⾥有⼀个关键的问题,在界⾯上点击8个⼩时以前任务执⾏,那么任务触发的时候,运⾏的是8个⼩时之前的时间,还是当前时间呢?
如果我们是通过之前的hour变量的来指定时间的,那任务运⾏的时间就是8个⼩时之前,任务当时触发的时间。
为什么呢?
我们在Jinja template⾥使⽤的变量 dag_run, execute_date这个并不是运⾏时变量,每次task触发,相关的上下⽂信息都会存到数据库⾥。
所以8个⼩时之后我们再重新运⾏task的时候,是从数据库中读取当时的上下⽂信息,⽽不是现在的信息。
如何查看任务log及所有任务的运⾏记录
查看所有任务的运⾏记录
1. DAG界⾯⾥的 [Graph View] -> 点击任务 -> [Task Instances]
2. 主菜单⾥的 [Browser] -> [Task Instances]
查看log
这就⽐较简单了
1. 点击 [Tree View] ⾥的⼩⽅块,可以查看log
2. Task Intances 列表最后⼀列,也可以查看log
如何在任务失败时发邮件(腾讯企业邮箱)
⾸先DAG的default_args需要配置
'email':['name@'],
'email_on_failure': True
修改airflow.cfg
smtp_host =
smtp_starttls = False
smtp_ssl = True
smtp_port = 465
smtp_mail_from = name@
smtp_user = name@
smtp_password = password
⾸先 smtp_ssl = True, smtp_port = 465 是⼀个重点。
再次smtp_mail_from和smtp_user都使⽤同⼀个有效的邮箱地址。
如何在任务失败时发消息到企业微信
有时候觉得发邮件可能还不够,想把失败消息发到企业微信,这样更能及时的发现问题。
添加企业微信依赖
airflow官⽅⽀持钉钉的通知,企业微信通知就是根据这个改动⽽来,代码有两个py⽂件:
把这两个py⽂件放到 dags ⽬录,也就是和dag的py⽂件放在⼀起。
在企业微信群中创建机器⼈
1. 右键点击群
2. 选择 [Add Group Robot],并创建
3. 获取机器⼈的key:右键 [View Information],可以得到⼀个URL
https:///cgi-bin/webhook/send?key=xxxxxx-xx-xx
这个key的值就是机器⼈的ID
4. 在airflow中创建企业微信的连接:[主菜单] -> [Admin] -> [Connections],配置填写:
Conn Id: wechat_robot
Conn Type: HTTP
Host: https://
Password: 前⾯得到的key值,也就是机器⼈的ID
在代码中使⽤
1. 代码中import WechatOperator
from wechat_operator import WechatOperator
2. 创建 failure call ⽅法:
def failure_callback(context):
dagConf = context['dag_run'].conf
taskInst = context['task_instance']
hour = None
if 'hour' in dagConf:
hour = dagConf['hour']
else:
hour = (taskInst.execution_date - timedelta(hours=24)).strftime('%Y%m%d%H')
message = 'Airflow任务失败:\n' \
'DAG: {}\n' \
'Task: {}\n' \
'时间: {}\n' \
.format(taskInst.dag_id,
taskInst.task_id,
hour)
return WechatOperator(
task_id='wechat_task',
wechat_conn_id='wechat_robot',
message_type='text',
message=message,
at_all=True,
).execute(context)
这个代码应该还是很好懂的,主要是为了创建 WechatOperator 对象。
有个逻辑来重新获取执⾏时间(这⾥必须使⽤代码,⽽不能直接使⽤Jinja template),为的是在通知⾥⾯可以直接看到是哪个时间出错了。
3. default_args添加 failure callback配置
'on_failure_callbak': failure_callback
结束语
到这⾥,总算是搭建好⼀个可以正式投⼊⽣产使⽤的环境了。
Airflow虽然很灵活,但是想真正满⾜⽣产需求,还是经历了不少痛苦。
特别是要求会使⽤python,加上airflow官⽅⽂档也不是很详细,这两点导致⼊门曲线太陡峭了。