Before we dive into Nginx’s structural analysis, let’s take a look at what makes a good Web server. This will help us understand the great architecture of Nginx.

1 Key constraints in Web server design

1.1 performance

1 Network Performance

Refers to the throughput of Web services on network communication under different loads. Network performance is constrained by bandwidth (the maximum throughput that can be achieved over a particular network connection).

2 Latency of a single request

For a user, the time between the first receipt of a user request by the server and the return of the response.

3 Network Efficiency

Commonly used methods to improve network efficiency include using long connections and using compression algorithms.

1.2 Scalability

An architecture that adds components to improve services, or allows components to interact with each other. Scalability can generally be improved by simplifying components, reducing coupling between components, and spreading services across many components.

1.3 the simplicity

The simplicity of the component. In general, we use the principle of separation of concerns to design components and the principle of generality for the overall structure.

1.4 Modifiability

In simple terms, modifiability is how easy it is to make changes to system functionality under the current architecture.

1 evolvability

Represents the extent to which changes to one component negatively affect other components.

2 Scalability

Represents the ability to add a new feature to the system without affecting other features.

3 Customizability

The ability to temporarily redefine the characteristics of a component or other structural element to provide a general service.

4 Configurability

After the Web service is deployed, the different capabilities are provided by modifying the configuration file provided by the service.

5 Reusability

This refers to the extent to which functional components in one application can be reused in other applications without modification.

1.5 the visibility

In a Web server, visibility typically refers to the extent to which the health of some key components can be monitored, such as the number of network connections being interacted in the service, cache usage, and so on.

1.6 Portability

A service that can run across platforms.

1.7 reliability

Reliability can be seen as the degree to which an architecture is vulnerable to system-level failures in the event of partial service failures.

2 Nginx architecture design

The design of Nginx pays particular attention to these 7 key points, and Nginx uses good modular design ideas.

2.1 Modular Design

Nginx has a basic interface, ngx_module_T, that all modules follow. The ngx_module_T interface has a type member, which specifies that Nginx allows module types to be defined during module design. The lowest level module in Nginx is the configuration type module (NGX_CONF_MODULE), which guides all modules to provide functionality around configuration items. Nginx includes five types of modules: core module, configuration module, event module, HTTP module, mail module.

2.2 Event-driven Architecture

Event-driven architecture refers to events generated by several event sources, collected and distributed by one or more event collectors (done by Nginx’s event module), and then “consumed” by many event handlers that register events of interest to them.

The server The difference between
The traditional Apache Use processes or threads as event consumers
Nginx An event consumer can only be a module, and only event collectors and distributors can occupy process resources

The simple model for Nginx to handle events is shown below: Five different events listed in the figure are collected in sequence during a single processing by the event collection, distributor process, and then events are distributed using the current process, which invokes the corresponding event consumer module to handle the event.

2.3 Multi-stage asynchronous processing of requests

Nginx’s event-driven architecture makes multi-stage asynchronous processing of requests a reality.

Multi-phase asynchronous processing of a request is to divide the processing of a request into multiple stages according to the way events are triggered, and each stage can be triggered by event collectors and distributors.

2.4 Management process, multi-work process design

Nginx adopts a master management process and multiple worker processes, as shown in the figure below.



The advantages of this design are: the concurrent processing capability of multi-core system; Multiple worker processes realize load balancing through process communication, that is to say, when a request comes, it is easier to be allocated to the worker process with a lighter load. The management process is responsible for monitoring the status of the worker process and managing its behavior.

2.5 Memory Pool Design

In order to avoid memory fragmentation and reduce the number of requests for memory from the operating system, Nginx designed a simple memory pool: multiple requests for memory are consolidated into a single operation, which greatly reduces the consumption of CPU resources and reduces memory fragmentation.

3 Framework process when Nginx starts

The start-up process is shown in the following flow chart:



Next, the key steps are explained:

Nginx provides services based on configuration files, so the first step is to determine the path of the configuration file nginx.conf.

2. In step 2, Nginx does not restart the service when it is upgradedA smooth upgrade), it will start the new version of Nginx without restarting the master process. At this point, the old version of the master process calls the execve system,Fork out the child process and then call exec to run the new programTo start the new version of the Master process.

3. Step 3 in the figure above, call the values of all core modulescreate_confMethod, that is to sayAll core modules are required to start constructing the structure for storing configuration items.

In step 4, you iterate through all the configuration items in nginx.conf and invoke the resolution configuration item method provided by the configuration module.

In step 5 of the figure above, all the NGINX_CORE_MODULE core modules are calledinit_confMethod,So that all core modules can do comprehensive processing after parsing configuration items.

In step 9, if nginx.conf is configured to work in single-process mode, the ngx_singLE_process_cycle method will be called to work in single-process mode.

7. Step 10 in the above figure, call the init_process method of all modules in single-process working mode. The single-process working mode startup is now complete and the normal working mode will be entered.

8. Step 11 to step 16 in the figure above, enter the master and worker working mode. The worker child, cache Manage child, cache Loader child starts to work.

4 How do worker processes work

Nginx signals and their corresponding global flag bit variables

signal Global flag bit variables in the corresponding process meaning
QUIT ngx_quit Gracefully close the process
The TERM or INT ngx_terminate Forcing a process to close
USR1 ngx_reopen Reopen all files
WINCH ngx_debug_quit No practical significance at present

There is also an NGx_Withdraw token bit, which is only used as a token bit on exiting by the method ngx_worker_process_cycle.

The working flow of worker process is as follows:

  1. First of all checkngx_exitingFlag bit. If it is 1, the process exits; otherwise, it starts checking, distributing, and processing events.
  2. And then determinengx_terminateWhether the flag bit is 1. If it is, the process is forcibly terminatedngx_quitWhether the bitcoinage is 1, and if so gracefully close the process with all listener handles also closed and the NGx_Withdraw flag set, otherwise proceed to the next step;
  3. Second, judgengx_reopenWhether the flag bit is 1 or not, if so reopen all files, going back to the first step to continue the determination of NGx_Withdraw.

5 How does the Master process work

First of all, it should be clear that the master process does not need to deal with network events. It does not need to be responsible for the execution of services. It can only restart services and smooth upgrades by managing worker sub-processes. The same goes for listing the various flag bits in the master process:

signal Global flag bit variables in the corresponding process meaning
QUIT ngx_quit Gracefully shut down the entire service
The TERM or INT ngx_terminate Forced shutdown of the entire service
USR1 ngx_reopen Reopen all files in the service
WINCH ngx_noaccept All child processes no longer accept to process new connections, as opposed to sending the QUIT semaphore to all child processes
USR2 ngx_change_binary Smooth upgrades to new versions of Nginx programs
HUP ngx_reconfigure Reread the configuration file and validate the service for the new configuration item
CHLD ngx_reap The ngx_reap_children method is responsible for monitoring all child processes when a child process unexpectedly terminates

How does the master process start a child process?

This is done simply through the fork system call. An unused ngx_PROCESS_t element is then selected from the NGX_PROCESSES array to store information about the child process.

Since the ngx_PROCESSES array holds information about all child processes, how does the state of those processes change?

Rely on the signal! For example, when several child processes exit unexpectedly, the parent process will receive the CHLD signal from the Linux kernel, due to the ngx_signal_handler method of the Nginx server: Set the SIG_REAP flag to 1 and call the ngx_process_get_STATUS method to change the state of all the child processes in the ngx_PROCESSES array (get the ID of the child process that ended unexpectedly with the WaitPID system call, The ngx_PROCESSES array is then traversed to find the ngx_PROCESS_t structure corresponding to the child process ID and exited it at position 1).

The master process works as follows:

  1. First of all,Determine the flag bit of NGx_REAP. If the value is 1, all child processes are monitoredngx_reap_childrenMethods throughngx_processesArray to check the state of each child process; If 0, go to the next step;
  2. thenDetermine the LIVE flag bit. ifliveFlag bit is 0 (All child processes have exited),ngx_terminateThe flag bit is 1 orngx_quitWhen the flag bit is 1, the master process starts to exitDelete the PID file that stores the process number, close the listening interface that is open in the process, and destroy the memory pool; Otherwise proceed to the next step;
  3. Secondly, the ngx_TERMINATE flag bit is determined. If it is 1, signal TERM is sent to all child processes to force the child process to exit, and then skip to step 1 to suspend the process and wait for the signal to be activated again. Otherwise, go to the next step.
  4. Determine the ngx_quit flag bit. If the value is 1, send QUIT signal to all child processes to gracefully exit the service, and close all listening interfaces. Similarly, skip to step 1 and suspend the process until the signal is activated. Otherwise, go to the next step.
  5. Determine the ngx_reconfigure flag bit. If the value is 1, the configuration file needs to be read again. Note that Nginx does not re-read the old worker and other child processes. Its strategy is to re-initialize the ngx_cycle_t structure to read the new configuration file and pull the new worker child process, destroying the old process. If 0, go to the next step;
  6. Check the ngx_restart flag bit, if it is 1, the new worker child process will be pulled, and at the same timengx_restartSet the value to 0, and then decide whether to start the cache Manager or Cache Loader process according to the cache module situationliveFlag position 1. Otherwise, go to the next step.
  7. Check the NGx_reopen flag bit. If it is 1, re-open all files with the position 0, and send a USR1 signal to all child processes to tell them to re-open all files. Otherwise proceed to the next step;
  8. Then,Check the ngx_Change_binary flag bit. If the value is 1, it indicates that smooth upgrade of Nginx is requiredngx_exec_new_binaryThe Nginx method starts the new version of the Nginx program with the new child process, while thengx_change_binaryFlag position 0;
  9. The last thing to check is the ngx_NOAccept flag bit. If it is 1, the QUIT signal is sent to all child processes, asking them to gracefully shut down the service while leavingngx_noacceptPosition 0,ngx_noacceptingSet it to 1 (to stop receiving new connections), and if it is 0, proceed to step 1 for the next loop.

6 summary

This machine focuses on the introduction of Nginx infrastructure, describes how the Nginx framework to start, initialize, load the code of each Nginx module, and how the worker process and master process in the work cycle. In fact, these mechanisms are based on Nginx’s core data structure, ngx_cyCLE_T.