Airflow运行Papermill调用Jupyter Notebook后ipykernel进程残留内存泄漏问题
解决方案
根因说明
你遇到的ipykernel_launcher残留进程问题,核心是Papermill执行Notebook时启动的内核进程在任务结束后未正常回收,通常是Sqlite连接未主动释放、内核异常卡住、Airflow任务异常退出未触发子进程清理、DAG代码语法错误导致任务状态异常这几个原因导致。
具体优化方案
1. 先修复DAG代码的明显语法错误
你当前的DAG存在两处会导致任务异常的问题,优先修复:
- 第1个PapermillOperator(
task_id=20210511_MMLIB)的定义末尾缺少闭合右括号),会导致任务加载异常 - 重复定义了两次
t9任务,会导致DAG逻辑混乱,删除多余的1个t9定义即可
2. Notebook侧主动释放资源
在每个Notebook的最后一个Cell添加如下代码,主动关闭资源并停止内核:
# 显式关闭所有Sqlite连接 # 如果你用的是sqlite3库 if 'conn' in locals(): conn.close() # 如果你用的是sqlalchemy引擎 if 'engine' in locals(): engine.dispose() # 主动停止当前内核,避免残留 import IPython IPython.Application.instance().kernel.do_shutdown(restart=False)
同时可以在Jupyter内核配置文件(通常是~/.ipython/profile_default/ipython_kernel_config.py)添加如下配置,禁止内核异常后自动重启:
c.IPKernelApp.exit_on_error = True c.KernelRestarter.restart_limit = 0
3. 优化PapermillOperator配置
给所有的PapermillOperator添加超时、内核回收相关参数,示例如下:
PapermillOperator( task_id="你的任务id", input_nb="你的输入notebook路径", output_nb="/tmp/out-{{ task_id }}-{{ execution_date }}.ipynb", # 增加task_id避免输出文件冲突 kernel_name="python3", # 显式指定内核,避免内核匹配异常 extra_arguments=[ "--KernelManager.shutdown_wait_time=1", # 内核停止等待超时时间,超时强制回收 "--stop_on_error=True" # 任务出错直接停止,不要挂住 ], execution_timeout=timedelta(hours=1) # 给每个任务加超时,避免无限挂住 )
4. 配置Airflow自动清理残留进程
4.1 增加DAG末尾的清理任务
在现有DAG的最后添加一个清理ipykernel进程的任务,放在t10之后即可:
clean_kernel_cmd = "sudo pkill -f 'ipykernel_launcher' || true" t11 = BashOperator( task_id='010_CLEAN_LEFTOVER_KERNEL', bash_command=clean_kernel_cmd ) # 调整依赖,让所有任务跑完再执行清理 t10 >> t11
命令末尾加|| true是为了避免没有残留进程时pkill返回非0导致任务失败。
4.2 调整Airflow Executor配置
根据你使用的Executor类型配置任务回收参数:
- 如果用LocalExecutor:在airflow.cfg中设置
local_worker_task_recycle = 10,每个worker进程跑满10个任务后自动重启,清理所有残留子进程 - 如果用CeleryExecutor:在airflow.cfg中设置
worker_max_tasks_per_child = 10,效果同上
5. 可选替代方案(彻底避免残留)
如果上述配置后仍有残留,可以放弃使用PapermillOperator,改用BashOperator直接调用papermill命令,用exec命令保证子进程随父进程一起退出:
run_nb_cmd = """ exec papermill /opt/airflow/script/PTS_Tools/xxx/xxx.ipynb /tmp/out-{{ task_id }}-{{ execution_date }}.ipynb """ t0 = BashOperator( task_id="20210511_MMLIB", bash_command=run_nb_cmd )
exec会把当前Bash进程替换为papermill进程,Airflow终止任务时会直接杀掉整个进程树,不会残留子进程。
内容的提问来源于stack exchange,提问作者elchapo
相关产品推荐
相关产品推荐

