Nginx (Engine X) is a high-performance HTTP and reverse proxy server, which is known for its high concurrency, high performance and low resource consumption. In this article, we will analyze in-depth how Nginx handles requests from principles, code and examples.
Nginx request processing principle
The principle of Nginx request processing mainly involves the following 6 core technical points:
- Event-driven model
- Asynchronous non-blocking processing
- Process Model
- Modular design
- Load balancing and reverse proxy
- Configuration file parsing
Next we will analyze them one by one:
Event-driven model
Nginx's event-driven model is based on non-blocking I/O and event loops. It uses multiplexing techniques (such as epoll, kqueue, etc.) to monitor multiple connections and calls the corresponding processor when an event occurs.
Multiplexing technology
Multiplexing technology is the key to the event-driven model. Nginx supports a variety of multiplexing mechanisms, including:
- epoll: an efficient multiplexing mechanism on Linux platform, suitable for a large number of concurrent connections.
- kqueue: Multiplexing mechanism for FreeBSD, OpenBSD, macOS and other platforms.
- select and poll: an earlier multiplexing mechanism, suitable for fewer concurrent connections.
Nginx will automatically select the optimal multiplexing mechanism according to the operating system.
Event loop
In Nginx, event loops are mainly responsible for monitoring and handling network events. The basic process is as follows:
- Initialization: Initialize the event module and configure event processing mechanism (such as epoll).
- Event listening: Listen to client connection requests, data readable and writeable events, etc.
- Event detection: Detect the occurrence of events through multiplexing mechanism.
- Event distribution: Distributes the detected events to the corresponding event processor.
- Event processing: Calling the callback function to handle specific events, such as reading requests, sending responses, etc.
Event handling
Nginx's event processing is implemented through a series of callback functions that are called at different event stages, including:
- Connection establishment: handles the establishment of a new connection.
- Request Read: Read request data from the client.
- Response sending: Send response data to the client.
- Connection Close: handles the closure of the connection.
###Worker Process
Nginx uses a multi-process architecture where each Worker process is an independent event-driven server. The Master process is responsible for managing the Worker process, while the Worker process is responsible for handling client requests. Each Worker process has its own event loop that can handle concurrent connections independently.
Asynchronous non-blocking processing
Asynchronous non-blocking means that Nginx can perform I/O operations without being blocked when processing a request. When the request is initiated, any time-consuming operations during the processing (such as disk I/O, network I/O) will not block the entire processing. Nginx handles other available events by placing these operations in asynchronous events waiting for completion, freeing the worker process.
Process Model
Nginx adopts the Master-Worker multi-process architecture, which includes a main process (Master Process) and one or more worker processes (Worker Processes). This architecture is designed to ensure separation of responsibilities in order to better manage system resources, concurrent request processing and failure recovery.
Master process
Responsibilities
- The main responsibility of the Master process is to manage and control the work process.
- Receive and process requests from external (such as administrators), such as configuring overloading, starting or shutting down Nginx.
- Read and parse configuration files at startup, initializing various global variables and resources.
Main functions
- Start and terminate Worker process: The Master process is responsible for starting the worker process in batches and restarting or terminating the worker process as needed.
- Management Signals: Listen and process system signals (such as SIGHUP is used for reload configurations, SIGTERM is used for shutting down the server, etc.).
- Smooth upgrade: When making configuration changes or performing Nginx version upgrades, you can achieve smooth upgrades by restarting the worker process continuously.
Worker process
Responsibilities
- Process all work on client requests. All actual network event processing is carried out in the work process, including accepting connections, reading requests, processing requests, sending responses, etc.
- Each Worker process is independent of each other and can handle independent connections.
Key features and functions
- No sharing status: Each Worker memory is independent of each other, which can avoid many lock problems that may arise during programming and improve parallel processing efficiency.
- Event-driven and non-blocking I/O: Worker processes use non-blocking I/O and event-driven mechanisms (such as epoll, kqueue, etc.) to process requests, which allows a large number of concurrent requests to be processed at the same time.
- Competition connection mechanism of process model: All Worker processes are equally requested for connections. Which process handles the new connection is determined by the port multiplexing technology and the operating system.
Communication between processes
Nginx's Master and Worker processes use UNIX signals for simple and effective communication, and the Master process's response to signals can bring about changes in overall behavior. For example:
SIGHUP: Reload the configuration, and the Master process will complete the following things:
- Generate a new configuration after checking for syntax errors.
- Start a new Worker process.
- Gradually close the old Worker process so that existing connections are not interrupted.
SIGTERM/SIGQUIT: Elegantly shut down the Nginx server. At this point, the Master process notifies the Worker process to close after all current requests have been completed.
SIGUSR1: Reopen the log file, usually used for log switching.
Modular design
Nginx is designed in a modular way, and different functions are accomplished through different types of modules (such as HTTP module, event module, Mail module, etc.). Each module provides specific functions for handling requests, and combines them to complete a complete HTTP service.
Load balancing and reverse proxy
Nginx can be configured as a reverse proxy that is forwarded directly to the backend server when processing requests. It can achieve load balancing and allocate requests based on set policies (such as polling, minimum connection).
Configuration file parsing
Nginx executes the processing definition of requests through configuration files. The configuration file specifies server blocks, location blocks, and other configuration instructions to indicate how Nginx responds to different HTTP requests.
Code Analysis
Nginx's code is written in C language. Let's analyze some key code snippets to understand how it works.
Start the process
Nginx starts frommain
The function starts, insrc/core/
In the file:
int main(int argc, char *const *argv) { ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; ngx_conf_t cf; // Initialize logs, signal processing, etc. ngx_log_error(NGX_LOG_NOTICE, log, 0, "nginx version: " NGINX_VERSION); // Get command line parameters process_args(argc, argv, &init_cycle); // Initialization cycle cycle = ngx_init_cycle(&init_cycle); // Looping the incoming request ngx_process_events_and_timers(cycle); return 0; }
ngx_init_cycle
Is a function that initializes Nginx cycles, including loading and parsing of configuration files.
Event loop
The core event loop is located inngx_process_events_and_timers
In the function:
void ngx_process_events_and_timers(ngx_cycle_t *cycle) { ngx_msec_t timer, delta; ngx_uint_t i; for (;;) { // Get the upcoming event and time timer = ngx_event_find_timer(); if (timer == NGX_TIMER_INFINITE) { timer = (ngx_msec_t) NGX_TIMER_INFINITE_VALUE; } // Wait for the event to arrive (void) ngx_process_events(cycle, timer, 0); // Call timer event ngx_event_expire_timers(); // Handle delayed file events ngx_handle_delayed_events(cycle); } }
In this loop, Nginx continuously waits for the event to occur, and then performs the corresponding operation according to the type of event.
Request processing
The actual HTTP request processing isngx_http_process_request
Completed in:
void ngx_http_process_request(ngx_http_request_t *r) { ngx_connection_t *c; ngx_http_core_main_conf_t *cmcf; c = r->connection; // The processing stage is divided into different handlers cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); // Match the location ngx_http_core_find_config_phase(r); // Perform access checks if (ngx_http_process_request_uri(r) != NGX_OK) { return; } // Execute input body filters if (ngx_http_read_client_request_body(r, ngx_http_request_body_handler) >= NGX_HTTP_SPECIAL_RESPONSE) { return; } // Call content handler ngx_http_core_content_phase(r); }
In this function, Nginx performs various stages of the request life cycle one by one, including URI parsing, permission checking, reading the request body, and final content processing.
Sample configuration
To better understand how Nginx handles requests, here we illustrate this by using a simple configuration example of static web server:
worker_processes 1; events { worker_connections 1024; } http { server { listen 80; server_name localhost; location / { root /var/www/html; index ; } } }
Configuration Analysis:
-
worker_processes 1;
: Specify Nginx to use a worker process. -
worker_connections 1024;
: Each worker process supports up to 1024 concurrent connections. -
http {}
: Start an HTTP configuration context. -
server {}
: Define a virtual server. -
listen 80;
: The server listens to port 80. -
server_name localhost;
: Specify the server name. -
location / {}
: Define the request processing location of the root directory. -
root /var/www/html;
: Map all requests to the root directory to the file system/var/www/html
Table of contents. -
index ;
: Specify the default homepage file.
Summarize
Nginx's design and implementation firmly grasps the goals of high performance and high concurrency. Through event-driven models, asynchronous processing, multi-process architecture and rich module systems, Nginx can not only efficiently handle HTTP requests, but also extremely flexible deployment and customization through a modular configuration system. By digging into Nginx's code and running principles, we can better understand and optimize our Nginx server configuration.
The above is a detailed article that will help you understand how Nginx handles requests. For more information about Nginx processing requests, please follow my other related articles!