Skip to content

Worker Architecture

Yury Selivanov edited this page Mar 1, 2018 · 2 revisions

The Python Worker is an asynchronous gRPC client controlled by the WebHost. The worker manages loading and execution of Python functions, as well as providing convenient Python wrappers for Azure Functions data types. Python worker is built on top of the asyncio module.

The following diagram shows the core building blocks of the worker:

            +-----------------+
            |     WebHost     |
            +-----------------+
                     ^
                     | gRPC messages
                     |
---------------------+-------------------------------
 Python Worker       |
                     v
           +------------------+          +----------+
     +-----|    Dispatcher    <----------> Bindings |
     |     +------------------+          +----------+
     |
     |                                +-------+
     |                           +----| func1 |
     |                           |    +-------+
+----v---------------+           |
|                    |           |    +-------+
| Functions Registry <-----------+----| func2 |
|                    |           |    +-------+
+--------------------+           |
                                 |       ...
                                 |
                                 |    +-------+
                                 +----| funcN |
                                      +-------+

The Dispatcher object, defined in azure.worker.dispatcher, is responsible for controlling a separate OS thread for sending and receiving gRPC messages; and for interpreting incoming gRPC requests for loading/invoking functions.

When a FunctionLoadRequest gRPC message arrives, the dispatcher object first tries to load the function with a loader.load_function call. If the function is successfully imported, it gets added to the Functions Registry.

Functions Registry, defined in azure.worker.functions, is responsible for validating loaded functions against the information in the FunctionLoadRequest message and for storing various associated metadata. During the validation process, it ensures that the functions signature matches arguments described in the FunctionLoadRequest. Type annotations, if present, are validated too. In the end, the Registry allows to fetch a Python function object along with its metadata via a function_id gRPC field.

When an InvocationRequest gRPC message arrives, the Dispatcher uses a Functions Registry object to get the loaded function object. It then uses the function metadata to unmarshal gRPC call arguments data into high-level Python datatypes described in the azure.functions module. The function then gets executed and all of its return values get marshalled back into an InvocationResponse gRPC message.

Marshalling and unmarshalling of Azure Functions datatypes happens in the azure.worker.bindings module. It contains concrete datatypes implementations, as well as converters to and from gRPC datatypes.