Understanding Nginx Architecture: Daemon Process, Worker Model, Connection Handling, and Core Data Structures
This article explains how Nginx runs as a daemon with a master process and multiple worker processes, details its asynchronous non‑blocking I/O model, connection and request handling, keep‑alive and pipeline mechanisms, and describes the key internal data structures such as connections, requests, arrays, queues, lists, strings, memory pools, hash tables, and red‑black trees.
Daemon Process
Nginx starts as a daemon on Unix systems, creating a master process that manages multiple worker processes.
Master and Worker Processes
The master process handles signals, monitors worker status, and restarts workers if they exit unexpectedly. Each worker process handles network events independently.
Worker Model and Process Advantages
Using separate processes avoids shared‑resource contention and eliminates the need for locks, improving stability and simplifying programming.
Multithreading Issues
Threads consume more memory and cause costly context switches; Nginx prefers a multi‑process model to avoid these overheads.
Asynchronous Non‑Blocking I/O
Nginx processes events asynchronously; it does not create threads for each request, resulting in low memory usage and no context switches.
Each request occupies minimal memory.
Event handling is lightweight.
Tests show that on a 24 GB machine Nginx can handle up to 2 million concurrent requests.
Connection Handling
Connections are defined in ngx_connection_t (found in src/core/ngx_connection.h/.c) and are based on TCP sockets (SOCK_STREAM).
Connection Process
After loading the configuration, Nginx creates the master process, opens listening sockets, forks workers, and each worker accepts connections, creating a ngx_connection_t structure to store client information.
struct ngx_connection_s {
void *data;
ngx_event_t *read;
ngx_event_t *write;
ngx_socket_t fd;
ngx_recv_pt recv;
ngx_send_pt send;
ngx_recv_chain_pt recv_chain;
ngx_send_chain_pt send_chain;
ngx_listening_t *listening;
off_t sent;
ngx_log_t *log;
ngx_pool_t *pool;
struct sockaddr *sockaddr;
socklen_t socklen;
ngx_str_t addr_text;
#if (NGX_SSL)
ngx_ssl_connection_t *ssl;
#endif
/* ... other flags ... */
};Connection Pool
Nginx maintains a pool of pre‑allocated ngx_connection_t structures per worker (size = worker_connections) and reuses them via a free‑connections list to avoid frequent allocations.
Accept Mutex and Competition
To prevent the “thundering herd” problem, Nginx uses accept_mutex so only one worker accepts new connections at a time, controlled by ngx_accept_disabled and related logic.
ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n;
if (ngx_use_accept_mutex) {
if (ngx_accept_disabled > 0) {
ngx_accept_disabled--;
} else {
if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
return;
}
if (ngx_accept_mutex_held) {
flags |= NGX_POST_EVENTS;
} else {
if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) {
timer = ngx_accept_mutex_delay;
}
}
}
}HTTP Request Processing
An HTTP request is represented by ngx_http_request_t, which encapsulates all request data.
struct ngx_http_request_s {
uint32_t signature; /* "HTTP" */
ngx_connection_t *connection;
void **ctx;
void **main_conf;
void **srv_conf;
void **loc_conf;
ngx_http_event_handler_pt read_event_handler;
ngx_http_event_handler_pt write_event_handler;
/* ... many fields ... */
ngx_uint_t method;
ngx_uint_t http_version;
ngx_str_t request_line;
ngx_str_t uri;
ngx_str_t args;
/* ... */
unsigned keepalive:1;
unsigned pipeline:1;
/* ... */
};The processing flow includes initializing the request, handling headers, body, invoking the appropriate handler, and running through phase handlers.
Keep‑Alive and Pipeline
Keep‑alive allows multiple requests over a single TCP connection, reducing the number of connections and time‑wait states. Pipeline uses the same connection to send multiple requests without waiting for each response, further improving efficiency.
Lingering Close
When closing a connection, Nginx waits briefly (lingering timeout) to read any remaining client data, preventing lost ACKs.
Core Data Structures
Arrays (ngx_array_t)
typedef struct {
void *elts; /* pointer to data */
ngx_uint_t nelts; /* number of elements */
size_t size; /* size of each element */
ngx_uint_t nalloc; /* allocated capacity */
ngx_pool_t *pool; /* memory pool */
} ngx_array_t;Dynamic array similar to a C++ vector.
Queues (ngx_queue_t)
struct ngx_queue_s {
ngx_queue_t *prev;
ngx_queue_t *next;
};Doubly‑linked list used for various internal queues.
Lists (ngx_list_t)
typedef struct {
ngx_list_part_t *last; /* last part */
ngx_list_part_t part; /* first part */
size_t size; /* size of each element */
ngx_uint_t nalloc; /* elements per part */
ngx_pool_t *pool; /* memory pool */
} ngx_list_t;Strings (ngx_str_t)
typedef struct {
size_t len; /* length */
u_char *data; /* pointer to data (not NUL‑terminated) */
} ngx_str_t;Memory Pool (ngx_pool_t)
struct ngx_pool_s {
ngx_pool_data_t d;
size_t max;
ngx_pool_t *current;
ngx_chain_t *chain;
ngx_pool_large_t *large;
ngx_pool_cleanup_t *cleanup;
ngx_log_t *log;
};Efficient memory allocator used throughout Nginx.
Hash Table (ngx_hash_t)
typedef struct {
ngx_hash_elt_t **buckets;
ngx_uint_t size;
} ngx_hash_t;Static hash built once during initialization; each bucket stores a contiguous block of elements.
Red‑Black Tree (ngx_rbtree_t)
struct ngx_rbtree_node_s {
ngx_rbtree_key_t key;
ngx_rbtree_node_t *left;
ngx_rbtree_node_t *right;
ngx_rbtree_node_t *parent;
u_char color;
u_char data;
};
struct ngx_rbtree_s {
ngx_rbtree_node_t *root;
ngx_rbtree_node_t *sentinel;
ngx_rbtree_insert_pt insert;
};Used for fast ordered lookups, e.g., timers.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
