airflow分布式部署、参数配置、优劣势分析、工程经验

这是第一篇博客,内容很简单,主要是记录工作中遇到的关于airflow分布式方面的经验。意义在于学习博客的使用,让自己养成技术博客的习惯。

目录

优劣势分析

分布式部署架构简析

分布式参数

调度、业务代码分离

注意事项


优劣势分析

airflow是一个编排、调度和监控workflow的平台,是一个工作任务的调度平台,其内置了比较全面实用的调度功能。下表列出了实际场景下,使用airflow和未使用airflow的对比。

未使用airflow

使用airflow

需要自己添加调度代码、调试复杂、功能单一、缺乏整体调度能力 框架调度,简单易用,更稳定,功能全面,可以整体调度
缺乏图形化能力,给任务的新增、排查等操作带来很多困难。特别是当任务较多,结构复杂的时候 内置树状图和流程图,清晰明了的展现任务拓扑结构
需要自己添加任务实时监测代码 任务实时状态返回网页界面,方便管理和查看
任务的各种操作大多需要编码或命令行完成,不够高效 常见操作方式转化为图形化界面,高效清晰
需要手动分离调度和业务代码 调度和业务代码分离,减少耦合性,方便运维和迭代

除了以上的优点,工程实践中有一个不足就是分布式部署有点麻烦,容易出错

 

分布式部署架构简析

airflow分布式部署、参数配置、优劣势分析、工程经验_第1张图片

如上图所示,airflow主要是通过参数控制调度。具体是,调度机和生产机的dag要放置在相同目录下,并且保持相同的代码。唯一的区别只是,调度机的dag不需要添加生产逻辑。下面给出了调度机的dag示例

#调度机中的dag代码示例
#生产机中的dag要放置到与调度机同样的目录下,并且将执行过程增加到*_function()

import airflow
from airflow.models import DAG
from airflow.operators.python_operator import PythonOperator

default_args = {
	'owner': 'xiaoming',
	'start_date': airflow.utils.dates.days_ago(1),
	'depends_on_past': False,
    # 失败发邮件
	'email': ['[email protected]'],
	'email_on_failure': True,
	'email_on_retry': True,
	# 重试相关
	'retries': 3,
	'retry_delay': timedelta(minutes=5),
	# 并发限制
	'pool': 'data_hadoop_pool',
	'priority_weight': 900,
	# 按机器名指定运行位置
	'queue': '66.66.0.66:8080'
}

dag = DAG(
    dag_id='daily', 
    default_args=default_args, #配置默认参数
    schedule_interval='0 13 * * *')

#生产机中,将具体执行过程放置在该函数下
def fetch_data_from_hdfs_function(ds, **kwargs):
	pass

#生产机中,将具体执行过程放置在该函数下
def push_data_to_mysql_function(ds, **kwargs):
	pass

fetch_data_from_hdfs = PythonOperator(
	task_id='fetch_data_from_hdfs',
	provide_context=True,
	python_callable=fetch_data_from_hdfs_function,
	dag=dag)

push_data_to_mysql = PythonOperator(
	task_id='push_data_to_mysql',
	provide_context=True,
	python_callable=push_data_to_mysql_function,
	dag=dag)

fetch_data_from_hdfs >> push_data_to_mysql

通过上述简单的部署方式,就可以实现airflow的分布式部署。团队在实践过程中,是使用一台生产机作为调度机,另外机器作为生产机。并且,选择其中一台负载压力不打的生产机作为后备调度机,防止调度机出现问题时,业务崩溃。

 

分布式参数

从分布式架构图中可以看出,airflow的调度逻辑主要是通过修改参数实现,示例代码如下:

#该task未修改参数,采用默认参数
fetch_data_from_hdfs = PythonOperator(
	task_id='fetch_data_from_hdfs',
	provide_context=True,
	python_callable=fetch_data_from_hdfs_function,
	dag=dag)

#该task修改通过指定参数,覆盖默认参数,调整调度行为
push_data_to_mysql = PythonOperator(
    task_id='push_data_to_mysql',
    queue='77.66.0.66:8080', #通过修改参数,调整调度
    pool='data_mysql_pool', #通过修改参数,调整调度
    provide_context=True,
    python_callable=push_data_to_mysql_function,
    dag=dag)

要注意的是,基于Java面向对象思想,会认为修改参数的方式是通过dag.setXxx()。这种方式更符合编程经验,但是airflow简化了此过程,直接可以在Operator中覆盖默认参数,就可以传递给dag进行调用。

 

调度、业务代码分离

上述的dag示例不够完善,因为生产机如果直接在dag中写处理逻辑,会让业务代码与调度代码耦合严重,不利于后期的维护与扩展。因此可以通过下述方式进行业务、调度代码分离。

airflow分布式部署、参数配置、优劣势分析、工程经验_第2张图片

如上图所示,把业务代码包装成函数引入生产机dag即可。示例代码如下

import xx.fetch_data_from_hdfs #将包装成函数的业务代码引入

#生产机中,将具体执行过程放置在该函数下
def fetch_data_from_hdfs_function(ds, **kwargs):
	if not fetch_data_from_hdfs: #判断业务代码是否执行成功,不成功报错
        raise AirflowException('run fail: fetch_data_from_hdfs')

fetch_data_from_hdfs = PythonOperator(
	task_id='fetch_data_from_hdfs',
	provide_context=True,
	python_callable=fetch_data_from_hdfs_function,
	dag=dag)

 

注意事项

调度机的dag和生产机的dag要保持一致。不一致时,不同的情况造成的后果不一样。比如,生产机参数与调度机不一致,比如指定的pool不存在,程序会正常运行。因为会使用调度机指定的pool。其余的不一致情况可能会造成程序崩溃。

你可能感兴趣的:(airflow分布式部署、参数配置、优劣势分析、工程经验)