Airflow这个神器似乎在国内用的并不算多,所以很多文档都不是很全。Celery也是个神器。本文主要记录Airflow如何将Executor切换成CeleryExecutor——只有切换成CeleryExecutor,才能实现sub节点的单节点重跑,否则整个sub节点都需要重跑。配置的坑比较多,也修改了源码,特此记录说明。
##1. 安装RabbitMQ
RabbitMQ是Celery官方推荐的生产级Broker(消息代理),RabbitMQ介绍有很多,建议仔细阅读一份,了解下再继续下面的配置,否则会碰到很多坑。
安装Erlang: CenterOS 7有默认安装
安装rabbitmq: yum install -y rabbitmq
启动rabbitmq: rabbitmq-server -detached
开机启动rabbitmq: chkconfig rabbitmq-server on
启动web监控台:rabbitmq-plugins enable rabbitmq_management
这里没有做特殊的设置,暂时使用默认配置
添加用户:
rabbitmqctl add_user celery celery@2017
rabbitmqctl add_vhost Celery
rabbitmqctl set_permissions -p Celery celery “." ".” “.*”
pip install celery
配置CeleryExecutor (rabbitmq支持)
安装airflow的celery和rabbitmq组件
pip install airflow[celery, rabbitmq]
主要配置四个参数,其他的并发量各位视自己的环境资源,适当配置大小
更改executor为 executor = CeleryExecutor
更改broker_url
broker_url = amqp://celery:celery@2017@localhost:5672/celery
Format explanation: transport://userid:password@hostname:port/virtual_host
更改celery_result_backend,我使用MySQL作为backend
celery_result_backend = db+mysql://airflow:airflow@2017@localhost:3306/airflow
Format explanation: transport://userid:password@hostname:port/virtual_host
另外,容易碰到一个问题
File "/usr/lib64/python2.7/site-packages/librabbitmq/__init__.py", line 199, in __init__
self.connect()
OperationalError: Couldn't log in: a socket error occurred
这个问题原因是因为broker_url写错了,结果vhost末尾不应该有/
,即配置amqp://celery:[email protected]:5672/celery/
不应该有末尾的/
,/
本身也是一个vhost。
##问题说明
搞了很久,查看了RabbitMQ控制页面,发现如果不启动work,消息是有正常写入MQ的,但是worker总是没有生效,后来查看日志,发现是问题1
导致。问题1解决后,还是不能正常启动任务(注意,webserver页面没有任何错误提示,一定要跟踪日志),再跟踪日志,发现了问题2
。
我的解决方式是开启,这个celery并不推荐。具体修改方式是:进入/usr/lib/python2.7/site-packages/airflow/executors
,修改celery_executor.py
源码文件
from celery import Celery,
platforms
在app = Celery(…)后新增
platforms.C_FORCE_ROOT = True
如上图中,红框圈定的就是修改的内容。再次重启airflow worker即可。
###问题2-Received and deleted unknown message. Wrong destination?!?
该问题导致比较奇葩,目测以为是broker_url配置错了,但是不是滴,谷歌才知道:
处理方式是
https://github.com/celery/celery/issues/3675
即卸载librabbitmq库,并且将ampq更改为pyampq,具体原因是
librabbitmq 1.6.1 doesn’t work with Celery4.0.2 #93
celery4.0.2版本与librabbitmq冲突,好吧,这样的bug一直没有修复。
###问题3-Unrecoverable error: PreconditionFailed(406, u"PRECONDITION_FAILED
又是个迷糊的问题,具体报错日志如下
[2017-02-20 15:34:40,265: CRITICAL/MainProcess] Unrecoverable error: PreconditionFailed(406, u"PRECONDITION_FAILED - inequivalent arg 'x-expires'for queue '[email protected]' in vhost 'celery': received the value '10000' of type 'signedint' but current is none", (50, 10), u'Queue.declare')
查看队列
发现已经发布成功了,可是就没有消费。。。
由于RabbitMQ控制台无法查看到queues,在服务器上rabbitmq查看队列正确姿势是
/usr/sbin/rabbitmqctl -n 节点名 list_queues -p vhost信息
其中,节点名可以通过rabbitmqctl status | grep node获取到,具体我的队列信息是
> rabbitmqctl -n rabbit@cdh list_queues -p celery
Listing queues ...
448cb450d455429a8342b38f5e123e1f 1
7444da414c6d42eba7ef615c55cd02a0 1
celery 0
[email protected] 0
celeryev.028b3030-bcda-4703-a0a5-10414d3571fc 0
celeryev.9b7e6329-b0b0-4cba-9575-8b4fcc1932e4 0
...done.
看到没有,消息不在celery中,而是在两个临时队列。这个很诡异了,难道是我之前的脏数据。重新再来一遍:
重置RabbitMQ数据
rabbitmqctl stop_app rabbitmqctl reset rabbitmqctl start_app
需要重新设置用户
rabbitmqctl add_user celery celery@2017 rabbitmq add_vhost Celery rabbitmqctl set_permissions -p Celery celery ".*" ".*" ".*"
搞到这儿的时候,有些恍然了,原来自己一直没有配置Celery的Exchange,所以会导致刚才发生的问题——没有按Topic的传递消息!发现这个问题后,不想配置exchange了,我直接偷懒的使用了vhost=/,配置airflow.cfg
broker_url = pyamqp://celery:celery@[email protected]:5672//
重新启动Airflow,OK了
##小结
可以满足Airflow的sub节点的Run Force的操作了。但是,依旧有蛋疼的事情,就是Run Force只能一个个执行,Sub节点下的Clear DownStream并不能拉起任务的重跑,这个问题,暂时可以通过重启Airflow webserver完成——但是,感觉很不友好。为什么Run的选项没有DownStream的选项?看来,只能在Sub节点Clear的时候,把任务也丢到任务队列中
##参考
http://blog.genesino.com/2016/05/airflow/#celeryexecutor-rabbitmq
http://www.cnblogs.com/Tommy-Yu/p/6230527.html