Apache HTTP Server Version 2.5

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 |
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.
CoreDumpDirectory
EnableExceptionHook
Group
Listen
ListenBacklog
MaxConnectionsPerChild
MaxMemFree
PidFile
PollersPerChild
ScoreBoardFile
SendBufferSize
StartServers
ThreadLimit
ThreadsPerChild
ThreadStackSize
Usermotorz 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:
PollersPerChild.ThreadsPerChild) that run
the actual connection and request processing pushed to them. Workers
never poll.MaxConnectionsPerChild
and the pipe-of-death / generation, signals the pollers to wind down,
and then joins them on exit.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.
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.
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.
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.
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.
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).
| 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.
StartServers 2 ThreadsPerChild 64 ThreadLimit 64 PollersPerChild 2
Available Languages: en