Basic#

Flow defines how your Executors are connected together and how your data flows through them.

Create#

The most trivial Flow is the empty Flow. It can be defined purely in Python or from a YAML file:

from jina import Flow

f = Flow()
jtype: Flow

Tip

An empty Flow contains only the Gateway.

../../../_images/zero-flow.svg

For production, it is recommended to define the Flows with YAML. This is because YAML files are independent of Python logic code and easy to maintain.

Conversion between Python and YAML#

Python Flow definition can be easily converted to/from YAML definition.

To load a Flow from a YAML file, use the load_config():

from jina import Flow

f = Flow.load_config('flow.yml')

To export an existing Flow definition to a YAML file use save_config():

from jina import Flow

f = Flow().add().add()  # Create a Flow with two Executors

f.save_config('flow.yml')

Start and stop#

When a Flow starts, all its added Executors will start as well, making it possible to reach the service through its API.

There are three ways to start a Flow. Depending on the use case, you can start a Flow either in Python, or from a YAML file, or from the terminal.

  • Generally in Python: use Flow as a context manager in Python.

  • As an entrypoint from terminal: use Jina CLI and a Flow YAML.

  • As an entrypoint from Python code: use Flow as a context manager inside if __name__ == '__main__'

  • No context manager: manually call start() and close().

from jina import Flow

f = Flow()

with f:
    pass
jina flow --uses flow.yml
from jina import Flow

f = Flow()

if __name__ == '__main__':
    with f:
        pass
from jina import Flow

f = Flow()

f.start()

f.close()

The statement with f: starts the Flow, and exiting the indented with block stops the Flow, including all Executors defined in it.

A successful start of a Flow looks like this:

../../../_images/success-flow.png

Your addresses and entrypoints can be found in the output. When enabling more features such as monitoring, HTTP gateway, TLS encryption, this display will also expand to contain more information.

Set multiprocessing spawn#

Some cornet cases require to force spawn start method for multiprocessing, e.g. if you encounter “Cannot re-initialize CUDA in forked subprocess”.

You may try JINA_MP_START_METHOD=spawn before starting the Python script to enable this.

JINA_MP_START_METHOD=spawn python app.py

Hint

There’s no need to set this for Windows, as it only supports spawn method for multiprocessing.

Serve forever#

In most scenarios, a Flow should remain reachable for prolonged periods of time. This can be achieved by jina flow --uses flow.yml from terminal.

Or if you are serving a Flow from Python:

from jina import Flow

f = Flow()

with f:
    f.block()

The .block() method blocks the execution of the current thread or process, which enables external clients to access the Flow.

In this case, the Flow can be stopped by interrupting the thread or process.

Server until an event#

Alternatively, a multiprocessing or threading Event object can be passed to .block(), which stops the Flow once set.

from jina import Flow
import threading


def start_flow(stop_event):
    """start a blocking Flow."""
    with Flow() as f:
        f.block(stop_event=stop_event)


e = threading.Event()  # create new Event

t = threading.Thread(name='Blocked-Flow', target=start_flow, args=(e,))
t.start()  # start Flow in new Thread

# do some stuff

e.set()  # set event and stop (unblock) the Flow

Visualize#

A Flow has a built-in .plot() function which can be used to visualize a Flow:

from jina import Flow

f = Flow().add().add()
f.plot('flow.svg')
../../../_images/flow.svg
from jina import Flow

f = Flow().add(name='e1').add(needs='e1').add(needs='e1')
f.plot('flow-2.svg')
../../../_images/flow-2.svg

One can also do it in the terminal via:

jina export flowchart flow.yml flow.svg 

One can also visualize a remote Flow by passing the URL to jina export flowchart.

Export#

A Flow YAML can be exported as a Docker Compose YAML or a Kubernetes YAML bundle.

Docker Compose#

from jina import Flow

f = Flow().add()
f.to_docker_compose_yaml()

One can also do it in the terminal via:

jina export docker-compose flow.yml docker-compose.yml 

This will generate a single docker-compose.yml file containing all the Executors of the Flow.

For an advance utilisation of Docker Compose with jina please refer to this How to

Kubernetes#

from jina import Flow

f = Flow().add()
f.to_kubernetes_yaml('flow_k8s_configuration')

One can also do it in the terminal via:

jina export kubernetes flow.yml ./my-k8s 

This will generate the necessary Kubernetes configuration files for all the Executors of the Flow. The generated folder can be used directly with kubectl to deploy the Flow to an existing Kubernetes cluster.

For an advance utilisation of Kubernetes with jina please refer to this How to

Tip

Based on your local Jina version, Jina Hub may rebuild the Docker image during the YAML generation process. If you do not wish to rebuild the image, set the environment variable JINA_HUB_NO_IMAGE_REBUILD.

See also

For more in-depth guides on Flow deployment, take a look at our how-tos for Docker compose and Kubernetes.