Multinode - Rapidly build distributed cloud applications in Python | Product Hunt

Resource management

Workers and autoscaling

Multinode is optimized to provision the appropriate amount of resources to match demand, while safeguarding against accidental overspending.

Functions

A function maintains a warm pool of workers, with each worker staying alive between successive function calls. A function will scale the number of workers in its pool to match the number of in-flight invocations, subject to certain constraints. You can specify these constraints using the max_workers, spare_workers and cooldown_period keyword arguments.

import multinode as mn

@mn.function(
  max_workers=30,
  spare_workers=2,
  cooldown_period=300
)
def square(x):
    return x ** 2

In the example above:

  • If there are 13 function invocations in flight at the current moment, then the framework will aim to scale the number of workers to 15 workers (i.e. 13 workers to meet the current demand, plus 2 additional spare_workers). Keeping spare workers alive is an effective way to avoid increased latency due to cold starts.
  • After a worker has completed a function invocation, it will remain alive for at least another 300 seconds (the cooldown_period), in anticipation of the load increasing again in the future.
  • When the system is idle, the number of workers falls to 2 (the number of spare_workers).
  • Under intense load, the number of workers can rise to up to 30 (the number of max_workers).

If cold starts are not a significant concern, then spare_workers should be set to zero to save costs.

The default values are max_workers=10, spare_workers=0 and cooldown_period=60. The highest allowed value for max_workers is 100.

Jobs

A job provisions a new worker per job execution, so concepts of spare workers and cooldown periods do not apply. However, it is possible to set a limit on the maximum concurrent executions of a job as a safeguarding measure.

@mn.job(max_concurrency=25)
def run_job(x):
    ###

The default value for max_concurrency is 10 and the maximum allowed value is 100.

Services

A service maintains a fleet of identical replica processes, each running the same API code behind the service's load balancer. The service will scale the number of replicas in order to maintain a certain target average CPU utilization across its replicas.

The autoscaling behaviour can be configured using the min_replicas, max_replicas and target_cpu_utilization keyword arguments.

import multinode as mn

@mn.service(
    port=80,
    min_replicas=3,
    max_replicas=20,
    target_cpu_utilization=0.4
)
def api():
    app.run()

Note that the default value for min_replicas is 2. This is to provide high availability, in case one replica suffers an unexpected hardware failure. If high availability is not a key requirement for your application, then set min_replicas to 1 to reduce costs.

The highest allowed value for max_replicas is 100. The target_cpu_utilization can take any decimal value between 0.05 and 0.95.

Scheduled tasks

A scheduled task provisions a new worker for each task execution, so there is nothing to configure.

Daemons

A daemon runs on a single process, so there is nothing to configure here either.

Previous
CPUs, GPUs and memory
Next
Quotas