From 90a688487220a10ce4de095c60d0468f6de4e9a0 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Mon, 28 Apr 2014 15:05:27 -0700 Subject: [PATCH] Add docs for the worker based engine (WBE) Begin to rework the twiki docs into a developer doc, moving items from the twiki to rst and adjusting examples to make a unified place where the worker model can be documented. Change-Id: I43ed828be33351b9fb6606317011e7204f61a136 --- doc/source/engines.rst | 18 +- doc/source/img/distributed_flow_rpc.png | Bin 0 -> 68549 bytes doc/source/index.rst | 2 +- doc/source/workers.rst | 328 ++++++++++++++++++++++++ taskflow/engines/worker_based/engine.py | 14 + 5 files changed, 345 insertions(+), 17 deletions(-) create mode 100644 doc/source/img/distributed_flow_rpc.png create mode 100644 doc/source/workers.rst diff --git a/doc/source/engines.rst b/doc/source/engines.rst index 359cea6b..6be17add 100644 --- a/doc/source/engines.rst +++ b/doc/source/engines.rst @@ -99,22 +99,8 @@ Worker-Based **Engine type**: ``'worker-based'`` -This is engine that schedules tasks to **workers** -- separate processes -dedicated for certain tasks execution, possibly running on other machines, -connected via `amqp `_ (or other supported -`kombu `_ transports). For more information, -please see `wiki page`_ for more details on how the worker based engine -operates. - -.. note:: - - This engine is under active development and is experimental but it is - usable and does work but is missing some features (please check the - `blueprint page`_ for known issues and plans) that will make it more - production ready. - -.. _wiki page: https://wiki.openstack.org/wiki/TaskFlow/Worker-based_Engine -.. _blueprint page: https://blueprints.launchpad.net/taskflow +For more information, please see :doc:`workers ` for more details on +how the worker based engine operates (and the design decisions behind it). Interfaces ========== diff --git a/doc/source/img/distributed_flow_rpc.png b/doc/source/img/distributed_flow_rpc.png new file mode 100644 index 0000000000000000000000000000000000000000..e2ad2198463f0fe5a84b03a6f39cdc8a96c0df19 GIT binary patch literal 68549 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 transports). + +.. note:: + + This engine is under active development and is experimental but it is + usable and does work but is missing some features (please check the + `blueprint page`_ for known issues and plans) that will make it more + production ready. + +.. _blueprint page: https://blueprints.launchpad.net/taskflow?searchtext=wbe + +Terminology +----------- + +Client + Code or program or service that uses this library to define flows and + run them via engines. + +Transport + protocol + Mechanism (and `protocol`_ on top of that mechanism) used to pass information + between the client and worker (for example amqp as a transport and a json + encoded message format as the protocol). + +Executor + Part of the worker-based engine and is used to publish task requests, so + these requests can be accepted and processed by remote workers. + +Worker + Workers are started on remote hosts and has list of tasks it can perform (on + request). Workers accept and process task requests that are published by an + executor. Several requests can be processed simultaneously in separate + threads. For example, an `executor`_ can be passed to the worker and + configured to run in as many threads (green or not) as desired. + +Proxy + Executors interact with workers via a proxy. The proxy maintains the underlying + transport and publishes messages (and invokes callbacks on message reception). + +Requirements +------------ + +* **Transparent:** it should work as ad-hoc replacement for existing + *(local)* engines with minimal, if any refactoring (e.g. it should be + possible to run the same flows on it without changing client code if + everything is set up and configured properly). +* **Transport-agnostic:** the means of transport should be abstracted so that + we can use `oslo.messaging`_, `gearmand`_, `amqp`_, `zookeeper`_, `marconi`_, + `websockets`_ or anything else that allows for passing information between a + client and a worker. +* **Simple:** it should be simple to write and deploy. +* **Non-uniformity:** it should support non-uniform workers which allows + different workers to execute different sets of atoms depending on the workers + published capabilities. + +.. _marconi: https://wiki.openstack.org/wiki/Marconi +.. _zookeeper: http://zookeeper.org/ +.. _gearmand: http://gearman.org/ +.. _oslo.messaging: https://wiki.openstack.org/wiki/Oslo/Messaging +.. _websockets: http://en.wikipedia.org/wiki/WebSocket +.. _amqp: http://www.amqp.org/ +.. _executor: https://docs.python.org/dev/library/concurrent.futures.html#executor-objects +.. _protocol: http://en.wikipedia.org/wiki/Communications_protocol + +Use-cases +--------- + +* `Glance`_ + + * Image tasks *(long-running)* + + * Convert, import/export & more... + +* `Heat`_ + + * Engine work distribution + +* `Rally`_ + + * Load generation + +* *Your use-case here* + +.. _Heat: https://wiki.openstack.org/wiki/Heat +.. _Rally: https://wiki.openstack.org/wiki/Rally +.. _Glance: https://wiki.openstack.org/wiki/Glance + +Design +====== + +There are two communication sides, the *executor* and *worker* that communicate +using a proxy component. The proxy is designed to accept/publish messages +from/into a named exchange. + +High level architecture +----------------------- + +.. image:: img/distributed_flow_rpc.png + :height: 275px + :align: right + +Executor and worker communication +--------------------------------- + +Let's consider how communication between an executor and a worker happens. +First of all an engine resolves all atoms dependencies and schedules atoms that +can be performed at the moment. This uses the same scheduling and dependency +resolution logic that is used for every other engine type. Then the atoms which +can be executed immediately (ones that are dependent on outputs of other tasks +will be executed when that output is ready) are executed by the worker-based +engine executor in the following manner: + +1. The executor initiates task execution/reversion using a proxy object. +2. :py:class:`~taskflow.engines.worker_based.proxy.Proxy` publishes task + request (format is described below) into a named exchange using a routing + key that is used to deliver request to particular workers topic. The executor + then waits for the task requests to be accepted and confirmed by workers. If + the executor doesn't get a task confirmation from workers within the given + timeout the task is considered as timed-out and a timeout exception is + raised. +3. A worker receives a request message and starts a new thread for processing it. + + 1. The worker dispatches the request (gets desired endpoint that actually + executes the task). + 2. If dispatched succeeded then the worker sends a confirmation response + to the executor otherwise the worker sends a failed response along with + a serialized :py:class:`failure ` object + that contains what has failed (and why). + 3. The worker executes the task and once it is finished sends the result + back to the originating executor (every time a task progress event is + triggered it sends progress notification to the executor where it is + handled by the engine, dispatching to listeners and so-on). + +4. The executor gets the task request confirmation from the worker and the task + request state changes from the ``PENDING`` to the ``RUNNING`` state. Once + a task request is in the ``RUNNING`` state it can't be timed-out (considering + that task execution process may take unpredictable time). +5. The executor gets the task execution result from the worker and passes it + back to the executor and worker-based engine to finish task processing (this + repeats for subsequent tasks). + +.. note:: + + :py:class:`~taskflow.utils.misc.Failure` objects are not json-serializable + (they contain references to tracebacks which are not serializable), so they + are converted to dicts before sending and converted from dicts after + receiving on both executor & worker sides (this translation is lossy since + the traceback won't be fully retained). + +Executor request format +~~~~~~~~~~~~~~~~~~~~~~~ + +* **task** - full task name to be performed +* **action** - task action to be performed (e.g. execute, revert) +* **arguments** - arguments the task action to be called with +* **result** - task execution result (result or + :py:class:`~taskflow.utils.misc.Failure`) *[passed to revert only]* + +Additionally, the following parameters are added to the request message: + +* **reply_to** - executor named exchange workers will send responses back to +* **correlation_id** - executor request id (since there can be multiple request + being processed simultaneously) + +**Example:** + +.. code:: json + + { + "action": "execute", + "arguments": { + "joe_number": 444 + }, + "task": "tasks.CallJoe" + } + +Worker response format +~~~~~~~~~~~~~~~~~~~~~~ + +When **running:** + +.. code:: json + + { + "status": "RUNNING" + } + +When **progressing:** + +.. code:: json + + { + "event_data": , + "progress": , + "state": "PROGRESS" + } + +When **succeeded:** + +.. code:: json + + { + "event": , + "result": , + "state": "SUCCESS" + } + +When **failed:** + +.. code:: json + + { + "event": , + "result": , + "state": "FAILURE" + } + +Usage +===== + + +Workers +------- + +To use the worker based engine a set of workers must first be established on +remote machines. These workers must be provided a list of task objects, task +names, modules names (or entrypoints that can be examined for valid tasks) they +can respond to (this is done so that arbitrary code execution is not possible). + +For complete parameters and object usage please visit +:py:class:`~taskflow.engines.worker_based.worker.Worker`. + +**Example:** + +.. code:: python + + from taskflow.engines.worker_based import worker as w + + config = { + 'url': 'amqp://guest:guest@localhost:5672//', + 'exchange': 'test-exchange', + 'topic': 'test-tasks', + 'tasks': ['tasks:TestTask1', 'tasks:TestTask2'], + } + worker = w.Worker(**config) + worker.run() + +Engines +------- + +To use the worker based engine a flow must be constructed (which contains tasks +that are visible on remote machines) and the specific worker based engine +entrypoint must be selected. Certain configuration options must also be +provided so that the transport backend can be configured and initialized +correctly. Otherwise the usage should be mostly transparent (and is nearly +identical to using any other engine type). + +For complete parameters and object usage please see +:py:class:`~taskflow.engines.worker_based.engine.WorkerBasedActionEngine`. + +**Example with amqp transport:** + +.. code:: python + + engine_conf = { + 'engine': 'worker-based', + 'url': 'amqp://guest:guest@localhost:5672//', + 'exchange': 'test-exchange', + 'topics': ['topic1', 'topic2'], + } + flow = lf.Flow('simple-linear').add(...) + eng = taskflow.engines.load(flow, engine_conf=engine_conf) + eng.run() + +**Example with filesystem transport:** + +.. code:: python + + engine_conf = { + 'engine': 'worker-based', + 'exchange': 'test-exchange', + 'topics': ['topic1', 'topic2'], + 'transport': 'filesystem', + 'transport_options': { + 'data_folder_in': '/tmp/test', + 'data_folder_out': '/tmp/test', + }, + } + flow = lf.Flow('simple-linear').add(...) + eng = taskflow.engines.load(flow, engine_conf=engine_conf) + eng.run() + +Limitations +=========== + +* Atoms inside a flow must receive and accept parameters only from the ways + defined in :doc:`persistence`. In other words, the task that is created when + a workflow is constructed will not be the same task that is executed on a + remote worker (and any internal state not passed via the + :doc:`inputs_and_outputs` mechanism can not be transferred). This means + resource objects (database handles, file descriptors, sockets, ...) can **not** + be directly sent across to remote workers (instead the configuration that + defines how to fetch/create these objects must be instead). +* Worker-based engines will in the future be able to run lightweight tasks + locally to avoid transport overhead for very simple tasks (currently it will + run even lightweight tasks remotely, which may be non-performant). +* Fault detection, currently when a worker acknowledges a task the engine will + wait for the task result indefinitely (a task could take a very long time to + finish). In the future there needs to be a way to limit the duration of a + remote workers execution (and track there liveness) and possibly spawn + the task on a secondary worker if a timeout is reached (aka the first worker + has died or has stopped responding). + +Interfaces +========== + +.. automodule:: taskflow.engines.worker_based.worker +.. automodule:: taskflow.engines.worker_based.engine +.. automodule:: taskflow.engines.worker_based.proxy diff --git a/taskflow/engines/worker_based/engine.py b/taskflow/engines/worker_based/engine.py index af178cb6..0c7702e1 100644 --- a/taskflow/engines/worker_based/engine.py +++ b/taskflow/engines/worker_based/engine.py @@ -20,6 +20,20 @@ from taskflow import storage as t_storage class WorkerBasedActionEngine(engine.ActionEngine): + """Worker based action engine. + + Specific backend configuration: + + :param exchange: broker exchange exchange name in which executor / worker + communication is performed + :param url: broker connection url (see format in kombu documentation) + :param topics: list of workers topics to communicate with (this will also + be learned by listening to the notifications that workers + emit). + :keyword transport: transport to be used (e.g. amqp, memory, etc.) + :keyword transport_options: transport specific options + """ + _storage_cls = t_storage.SingleThreadedStorage def _task_executor_cls(self):