linear_flow线性工作流

232 阅读1分钟

线性工作流 介绍

线性工作流 中下一个任务必须等待上一个任务被完成,才可以 执行下一个任务

我们来看一下 openstack 提供的 linear_flow 的一个实际 demo

这个 flow 的作用就是 创建一个 volume 。

官方注释 写的很明白,得到 执行 以下 6个步骤的 工作流。

api_flow = linear_flow.Flow(flow_name) 这句话就类似于 我们之前 讲异步提到的 job_list[] 空列表

之后 api_flow.add(QuotaReserveTask(), EntryCreateTask(db_api), QuotaCommitTask()) 就是给这个 空列表中 按照任务顺序添加 需要被执行的任务。

更棒的地方在于,我们之前的课程中,是自己 循环 启动了一个个 异步任务。 但是 api_flow 自身就拥有 run 方法

run 中的 flow_engine 就是 通过 get_flow 方法得到的,他会保证 linear_flow 中的任务,得到 "异步的启动,并保证 有序的执行"

我们要理解 "异步的启动,并保证 有序的执行" 如果我们单纯 需要 有序执行,我们只是 f1();f2();f3(); 即可 但是 f1, f2 ,本身 很可能 并不是 计算 密集型操作,他们并不比阻塞 cpu。 所以我们要 "异步的启动,并保证 有序的执行"

with flow_utils.DynamicLogListener(flow_engine, logger=LOG):
  flow_engine.run()
  vref = flow_engine.storage.fetch('volume')
  LOG.info(_LI("Volume created successfully."), resource=vref)
  return vref

get_flow

def get_flow(db_api, image_service_api, availability_zones, create_what,
             scheduler_rpcapi=None, volume_rpcapi=None):
    """Constructs and returns the api entrypoint flow.

    This flow will do the following:

    1. Inject keys & values for dependent tasks.
    2. Extracts and validates the input keys & values.
    3. Reserves the quota (reverts quota on any failures).
    4. Creates the database entry.
    5. Commits the quota.
    6. Casts to volume manager or scheduler for further processing.
    """

    # ACTION = 'volume:create'
    flow_name = ACTION.replace(":", "_") + "_api"
    api_flow = linear_flow.Flow(flow_name)

    api_flow.add(ExtractVolumeRequestTask(
        image_service_api,
        availability_zones,
        rebind={'size': 'raw_size',
                'availability_zone': 'raw_availability_zone',
                'volume_type': 'raw_volume_type'}))
    api_flow.add(QuotaReserveTask(),
                 EntryCreateTask(db_api),
                 QuotaCommitTask())

    if scheduler_rpcapi and volume_rpcapi:
        # This will cast it out to either the scheduler or volume manager via
        # the rpc apis provided.
        api_flow.add(VolumeCastTask(scheduler_rpcapi, volume_rpcapi, db_api))

    # Now load (but do not run) the flow using the provided initial data.
    return taskflow.engines.load(api_flow, store=create_what)