Apache Airflow任务卡在“ up_for_retry”状态

时间:2018-12-12 13:31:51

标签: airflow

我一直在我们的系统上设置气流集群,并且以前一直在工作。我不确定该做些什么。

我有一个DAG,我想按计划运行。为了确保它能正常工作,我还想手动触发它。目前,这两个似乎都不起作用,并且似乎没有为任务实例编写日志。唯一可用的日志是通常看起来很健康的气流调度程序日志。

我经常收到以下消息:

Task is not ready for retry yet but will be retried automatically. Current date is 2018-12-12T11:34:46.978355+00:00 and task will be retried at 2018-12-12T11:35:08.093313+00:00.

但是,如果我稍等片刻,除了时间稍有改变外,还会再次显示完全相同的消息。因此,似乎从未真正尝试过执行任务。

我正在使用LocalExecutor,任务是SSHOperator。下面的简化代码。它要做的就是将ssh切换到另一台机器上,并使用预定的目录结构启动一堆应用程序。

DB_INFO_FILE = 'info.json'
START_SCRIPT = '/bin/start.sh'
TIME_IN_PAST = timezone.convert_to_utc(datetime.today() - 
timedelta(days=1))

DEFAULT_ARGS = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': TIME_IN_PAST,
    'email': ['some_email@blah.com'],
    'email_on_failure': False,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=1),
}

def _extract_instance_id(instance_string):
    return re.findall(r'\d+', instance_string)[0]

def _read_file_as_json(file_name):
    with open(file_name) as open_file:
         return json.load(open_file)

DB_INFO = _read_file_as_json(DB_INFO_FILE)
CONFIG_CLIENT = ConfigDbClient(**DB_INFO)

APP_DIRS = CONFIG_CLIENT.get_values('%my-app-info%')

INSTANCE_START_SCRIPT_PATHS = {
    _extract_instance_id(instance_string): directory+START_SCRIPT
    for instance_string, directory in APP_DIRS.items()
    }

# Create an ssh hook which refers to pre-existing connection information
# setup and stored by airflow
SSH_HOOK = SSHHook(ssh_conn_id='my-conn-id')

# Create a DAG object to add tasks to
DAG = DAG('my-dag-id',
          default_args=DEFAULT_ARGS)

# Create a task for each app instance.
for instance_id, start_script in INSTANCE_START_SCRIPT_PATHS.items():
    task = SSHOperator(
        task_id='run-script-{0}'.format(instance_id),
        command='bash {0}'.format(start_script),
        ssh_hook=SSH_HOOK,
        dag=DAG)

当我通过命令行而不是通过UI单独运行任务时,它可以工作。看来我可以运行任务,但是我根本无法触发DAG运行。我还尝试了start_date s和interval计划的许多组合,也只是为了进行健全性检查。

有什么想法吗?

是的,我知道这个问题以前曾被问过,我已经研究了所有问题,但是没有解决方案对我有帮助。

2 个答案:

答案 0 :(得分:0)

哦。您的start_date的更改速度或速度比计划间隔时间长。

调度器每隔几秒钟就会看到以下内容:

start_date: 2018-12-11T12:12:12.000Z  # E.G. IFF now is 2018-12-12T12:12:12.000Z, a day ago
schedule_interval: timedelta(days=1)  # The default

这是调度程序运行DAG所需要的:上一次运行发生是在一个以上调度间隔之前。如果没有发生预定的运行,则自start_date起已经过去了一个完整的预定间隔,则可以立即开始第一个预定的运行,因为这是最早的允许日期execution_date。在这种情况下,应创建将dag_run设置为该间隔时间段的开始的execution_date。然后,只要task_instance task_instance在DAG的execution_date之后,就可以为DAG中满足依赖关系的任何任务创建start_date dag_run对象上,但通过在检查dag的状态时加载DAG文件来重新计算。

因此,由于开始日期随着间隔的变化而不断变化,因此它不会自动排定。但是,如果是-2d,则至少要安排一次跑步,然后再进行其他跑步,必须等到安排之后的1d。不过,如果您仅在datetime上设置一个固定的start_date,则会更容易。

但是手动运行中那些奇怪的重试呢?

您确实开始了一两次手动运行。除非您另外指定,否则这些运行将当前时间作为execution_date。这应该在start_date之后,至少要到明天,这应该清除它们的运行。但是,在您的日志中,您似乎看到它们正在失败并且被标记为重试,并且也没有减少重试次数。我不确定为什么会这样,但是SSHOperator可能有问题吗?

您是否另外安装了[ssh]气流,以便在Web服务器和调度程序上都满足SSHOperator的依赖性(特别是paramikosshtunnel)?其中之一正在工作,因为我认为它是根据添加到数据库中后在UI中进行解析和显示的。

执行后会得到什么?

airflow test my-dag-id run-script-an_instance_id 2018-12-12T12:12:12

您知道调度程序和Web服务器正在循环填充其DAG包,因此每天要重新运行此DAG文件几次1000次,重新加载json(它是本地访问权限,因此类似于导入模块),然后重新创建{ {1}}与数据库查找。我看不到任何设置此挂钩的幻想,为什么不从SSHHook删除ssh_hook并用SSHOperator代替它以便可以在执行时创建一次? 我怀疑这是导致重试的问题,但是重试只是向前滚动。

答案 1 :(得分:0)

我有一个任务在up_for_retry停留了将近24小时,然后才注意到,它与start_date,end_date或任何其他经典初学者的问题无关。

我求助于阅读源代码,并发现Airflow如果将up_for_retry任务作为回填DAG运行的一部分,则会以不同的方式对待。

因此,我连接到元数据数据库,并在与卡住的任务相对应的backfill_行中将scheduled__改为dag_run。 Airflow立即开始执行卡住的任务。