Implementation of HTTP Auth Server Round-Robin and
Memory Caching for NGINX Email Proxy
June 6, 2007
Md. Mansoor Peerbhoy <mansoor@zimbra.com>
...
Flow of an NGINX worker process
After the main NGINX process reads the configuration file and forks
into the configured number of worker processes, each worker process
enters into a loop where it waits for any events on its respective
set of sockets.
Each worker process starts off with just the listening sockets,
since there are no connections available yet. Therefore, the event
descriptor set for each worker process starts off with just the
listening sockets.
(NOTE) NGINX can be configured to use any one of several event
polling mechanisms:
aio/devpoll/epoll/eventpoll/kqueue/poll/rtsig/select
When a connection arrives on any of the listening sockets
(POP3/IMAP/SMTP), each worker process emerges from its event poll,
since each NGINX worker process inherits the listening socket. Then,
each NGINX worker process will attempt to acquire a global mutex.
One of the worker processes will acquire the lock, whereas the
others will go back to their respective event polling loops.
Meanwhile, the worker process that acquired the global mutex will
examine the triggered events, and will create necessary work queue
requests for each event that was triggered. An event corresponds to
a single socket descriptor from the set of descriptors that the
worker was watching for events from.
If the triggered event corresponds to a new incoming connection,
NGINX accepts the connection from the listening socket. Then, it
associates a context data structure with the file descriptor. This
context holds information about the connection (whether
POP3/IMAP/SMTP, whether the user is yet authenticated, etc). Then,
this newly constructed socket is added into the event descriptor set
for that worker process.
The worker now relinquishes the mutex (which means that any events
that arrived on other workers can proceeed), and starts processing
each request that was earlier queued. Each request corresponds to an
event that was signaled. From each socket descriptor that was
signaled, the worker process retrieves the corresponding context
data structure that was earlier associated with that descriptor, and
then calls the corresponding call back functions that perform
actions based on the state of that connection. For instance, in case
of a newly established IMAP connection, the first thing that NGINX
will do is to write the standard IMAP welcome message onto the
connected socket (* OK IMAP4 ready).
By and by, each worker process completes processing the work queue
entry for each outstanding event, and returns back to its event
polling loop. Once any connection is established with a client, the
events usually are more rapid, since whenever the connected socket
is ready for reading, the read event is triggered, and the
corresponding action must be taken.