Airflow pipeline作业流遇到这样一个问题:使用paramiko下载小文件成功,下载大文件出现Server connection dropped
报错。
问题描述
下图可以看到aml_dwn_native_gz
、aml_dwn_deleted_daily
、aml_dwn_premium_daily
三个作业执行成功,但aml_dwn_premium_fullsize_gz
出现报错。
四个下载作业均使用ShortCircuitOperator
,代码块如下所示,唯一不同的是传入的参数filename1
和filename2
在k8s配置文件中对应的文件名不同。
|
|
日志分析
|
|
可以看到,中间有20多分钟持续输出heartbeat warning message,于是以为Server connection dropped
报错是Airflow hearbeat warning message太多所致,其它3个paramiko download作业能够执行成功,唯有这一个因为待下载的文件size巨大(670MB),需要耗费的时间较多,Airflow打印了很多hearbeat warning message,从log日志中看到cpu time经常性地被sleep函数占用,故而无法给paramiko download作业分配执行时间。
原因排查
第一时间在Stack Overflow上面发帖求助。
Stack Overflow求助帖:Airflow heartbeat warning log cause ssh connection dropped
后来翻来覆去地看Airflow local_task_job.py
程序源码,发现不是hearbeat warning message的问题,即使把这些warning message给disable掉,我推断情况可能还是会如此(这里因为k8s中跑的Airflow image我没有权限修改,并没有尝试)。
后来搜索paramiko EOFError
报错,发现很多人遇到了类似的问题,详细见别人在GitHub上发的这个求助帖。
GitHub求助帖:SFTP: Downloading Large Files Hangs
为什么使用paramiko下载小文件能成功,下载大文件会报错,原因目前并没有探明。
我的一个推测是,paramiko创建ssh连接后,使用ssh对象实例化一个sftp对象,通过这个sftp对象去完成文件下载动作,由于large size文件下载需要耗费大量时间,ssh对象在下载过程中被Python虚拟机gc机制当作垃圾给回收掉了,这样就出现了”Server connection dropped”。
解决方法
最后参照GitHub上该博主的建议,使用shutil.copyfileobj替换paramiko sftp.get下载功能,测试后发现large size文件可以下载成功。
|
|
后续有新的发现,再做更新。
参考资料