httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Stoddard" <redd...@attglobal.net>
Subject Re: Windows 2.0 MPM design issues
Date Wed, 31 May 2000 13:52:14 GMT

> MPM's are how the server maps a request to an execution
> primitive.  Basically, the server starts configures itself and calls the
> MPM code.
>
> The MPM is responsible for starting child processes and monitoring
> them.  It is also responsible for starting threads within the child
> process and having those threads (whether there be 1 or more) accept on
> the socket.  Once a request is made, the MPM is responsible for having an
> execution primitive handle the request.  For all of the current MPM's the
> same primitive that accepted the connection also handles request, however
> it would be possible to have one thread accept all connections and hand
> the requests off to other threads to actuall serve the request.
>
> LAstly, the MPM is responsible for managing the threads and other child
> processes.  And killing them when a restart/shutdown is requested.
>

Very good MPM overview. Continue with Win32 specific MPM details...

The WIN32 MPM creates two processes. The parent process and the parent process creates a child
process. The child process is multithreaded and is responsible for processing all HTTP requests.

The parent process:
1. Creates the AcceptEx IO Completion Port (IOCP for short) (I won't attempt explain this.
I'd take
too many words)
2. Opens all the listen sockets
3. Creates the child process
4. Passes a duplicated IOCP handle to the child (parent communicates to the child via pipe,
NOT
shared memory)
5. Passed duplicated listen socket handles to the child (via a pipe)
6. Waits for a restart or shutdown event (from an external process) or a child exit (normal
or
abnormal)
7. When one of the above events is signaled, the parent does the right thing (restarts the
failed
child process, signals the child process to die gracefully and optionally on restart, restarts
a new
child process to take the place of the old child process.)
8. Thats it! The parent process job is very simple.

Steps 1, 2, 4 & 5 could be done directly in the child process. Doing them in the parent
process
allows the sockets (and pending connections in the listen queue) to be maintained across a
server
restart. Doing these steps in the child process would cause all pending connections to be
dropped
across a restart.

The main thread in the child process:
1. Receives the IOCP and duplicated sockets
2. Does initialization required to begin accepting connections
3. Creates a pool of worker threads which accept requests off the listen sockets (the details
differ
a bitr depending on whether you are on NT or not). When a connection is received, a thread
accepts
the connection and processes the request that comes in on that connection.
4. Starts accepting requests
    95/98 requests are accepted on a seperate thread. NT uses an IOCP.
5. The main child thread then waits for a shutdown event (or on NT, a server maintenance event)

If the main thread received a server maintenance event, it does some IOCP magic to increase
the
number of connections that can be handled). When it receives a shutdown event (either generated
by a
worker thread or generated by the parent process), it shutdowns the worker threads gracefully
and
eventually exits.

There is a start_mutex which prevents more than one child process from accepting requests
at once.

The WIN32 MPM uses threads as the "execution primitive". Apache 1.3 on Windows used threads
as well.
The NT specific code uses IO Completion ports and does accepts asynchronously. Worker threads
are
dispatched off the IOCP in LIFO order, which is pretty cool. This is the first step to getting
to a
fully asynchronous server (which is my goal). What does this mean? Today the server is not
fully
asynchronous, which means that you require 1 thread per concurrently connected client. 2000
concurrent clients implies the need for 2000 threads. Now threads are lighter weight than
processes,
but that still cost resources. A fully async server could handle those 2000 concurrent clients
with
1 thread (or realistically, a few threads) because that thread would NEVER block on network
I/O.

Hope this helps.

Bill Stoddard





Mime
View raw message