<-
Apache > HTTP Server > Documentation > Version 2.5 > Modules

Apache MPM motorz

Available Languages:  en 

Description:A lean, fast, self-contained event-driven Multi-Processing Module built on the APR pollset and thread pool especially suited as a reverse proxy
Status:MPM
Module Identifier:mpm_motorz_module
Source File:motorz.c

Summary

The motorz Multi-Processing Module (MPM) is an asynchronous, event-driven implementation. It combines a prefork-style fixed pool of child processes with an event core built on APR's pollset and a shared thread pool. Each child runs one or more dedicated poller threads that watch sockets and timers, dispatching ready I/O events and expired timers to a pool of worker threads. The workers never poll; they only process the connection/request work pushed to them.

The design goal is a fast, efficient, single, compact MPM that runs on modern Unix platforms by leaning on APR as much as possible, while still supporting the asynchronous connection handling needed for efficient keep-alive and HTTP/2.

To use the motorz MPM, add --with-mpm=motorz to the configure script's arguments when building the httpd, or build it as a loadable module with --enable-mpms-shared=motorz.

Topics

Directives

Bugfix checklist

See also

top

How it Works

motorz uses prefork as the framework for process management and an event core for connection handling. A single control process (the parent) launches a fixed number of child processes, as set by the StartServers directive. Unlike worker and event, the number of children does not float with load: motorz maintains a static pool, replacing children one-for-one as they exit. Concurrency within a host is scaled by adding worker threads (ThreadsPerChild) and, where the poll/dispatch path is the bottleneck, poller threads (PollersPerChild), rather than by spawning more processes.

Each child process runs:

A connection is sharded to one poller at accept time (round-robin) and bound to it for its whole lifetime: it re-arms in, and times out on, that poller's pollset and timer ring. Using multiple pollers lifts the single-poll-thread throughput ceiling, so accept, event dispatch and timer expiry scale with PollersPerChild instead of being serialized on one thread.

While the parent process is usually started as root under Unix in order to bind to port 80, the child processes and threads are launched by the server as a less-privileged user. The User and Group directives are used to set the privileges of the Apache HTTP Server child processes. The child processes must be able to read all the content that will be served, but should have as few privileges beyond that as possible.

MaxConnectionsPerChild controls how frequently the server recycles processes by retiring old ones and launching new ones.

top

Asynchronous connection handling

motorz reports itself as an asynchronous MPM. When a worker finishes the active phase of a connection (for example, an HTTP keep-alive connection between requests, or a connection waiting on further I/O), it hands the socket back to its poller rather than holding a worker thread idle. The poller waits for the next event on that socket, bounded by the configured Timeout, and re-dispatches the connection to a worker only when there is work to do. This frees worker threads from idle keep-alive connections and is what allows efficient HTTP/2 handling, where the master connection is handed back to the MPM between requests.

Lingering close is also non-blocking: instead of blocking a worker for the duration of the lingering-close timeout, the draining socket is handed back to the poll loop with a bounded linger timeout, so the worker is returned to the pool immediately.

Modules that take a connection fully asynchronous (suspending it and resuming it later) are supported; a suspended connection is parked and re-armed on its owning poller when resumed.

top

Admission control

To keep a child safe under overload, motorz applies listener backpressure. When the worker pool saturates, the poller that owns the listening sockets removes them from its pollset and stops accepting; it re-adds them once the backlog drains. This keeps the work queue and per-connection memory bounded rather than growing without limit. The decision is based on the worker pool's idle, pending and active-thread counts, with hysteresis to avoid flapping the listeners on and off.

ThreadsPerChild and admission control

Because the admission-control low-water mark is a fraction of ThreadsPerChild, very small values (in particular ThreadsPerChild 1) cause the listeners to re-enable only when the work queue is completely empty, which severely degrades throughput. A value of ThreadsPerChild of at least 4 is strongly recommended; the server emits a warning otherwise.

top

Relationship to other MPMs

motorz uses prefork for process management and an APR thread pool for workers, with pollers dispatching work to that pool. This is distinct from event's listener/worker/fdqueue design, in which the worker threads themselves re-arm a shared, thread-safe pollset.

Whether additional pollers help depends on the workload. If the worker threads are the CPU bottleneck—typical for real request processing—the poller threads are not the limiting factor, and a PollersPerChild beyond one or two yields little. The multiple-poller design removes motorz's structural single-thread ceiling, but per-host throughput is still governed by worker CPU.

No ServerLimit / dynamic process scaling

Unlike worker and event, motorz does not scale the number of child processes with load and does not provide a separate ServerLimit ceiling. The process pool is fixed at StartServers, which therefore acts as the hard daemon limit, and there are no MinSpareThreads / MaxSpareThreads / MaxRequestWorkers controls. Scale concurrency with ThreadsPerChild (and, if the poll path saturates, PollersPerChild).

top

PollersPerChild Directive

Description:Number of poll threads per child process
Syntax:PollersPerChild number
Default:PollersPerChild 0
Context:server config
Status:MPM
Module:motorz

The PollersPerChild directive sets the number of poller threads created in each child process. Each poller owns its own pollset, timer ring and connection-recycle list, and handles a shard of the child's connections, so adding pollers raises the rate at which a single child can accept connections and dispatch I/O events and timer expiries.

A value of 0 (the default) means auto: the number of pollers is derived from the number of online CPUs, capped at a built-in maximum. In all cases the number of pollers is clamped so that it never exceeds ThreadsPerChild and is never less than one.

Because event dispatch is rarely the bottleneck for real request processing—worker CPU usually is—values beyond one or two seldom improve throughput. Raising PollersPerChild is mainly useful for workloads dominated by very high connection churn or large numbers of idle, event-driven connections, where the poll/accept path itself becomes the limit.

Example

StartServers       2
ThreadsPerChild   64
ThreadLimit       64
PollersPerChild    2

Available Languages:  en