Nginx process structure

Nginx has two types of process structures: single-process and multi-process. By default, there is only one worker process after compilation and installation, which can be configured in nginx.conf.

Recommended: The number of worker processes should be equal to the number of CPU cores. For high-traffic concurrent scenarios, increase the number of worker processes to 2 CPU cores

A single process can only be used for development debugging; Multi-process ensures that Nginx is robust enough to take advantage of multi-core features.

Why multi-process and not multi-thread?

The core purpose of Nginx is to maintain high availability and reliability. If Nginx uses a multi-threaded structure, threads share an address space, and if a third party module raises a segment error in the address space or an address out of bounds, it will cause the entire Nginx process to hang up. This is not the case when using the multi-process model!

Adjust the number of work processes?

After nginx is compiled and installed, one main process and one worker process are started by default. This does not meet nginx performance requirements. We can modify the nginx configuration file to set the number of worker processes:

#user molong;worker_processes auto; Error_log logs/error.log; // The default value is 1. If you change the value to auto, you can set the number of working processes according to the number of CPU cores. error_log logs/error.log notice; error_log logs/error.log info; pid logs/nginx.pid;Copy the code

If set manually, you can run lscPU to check the number of CPU cores:

Two. Semaphore

2.1. What is a semaphore?

Semaphore is one of the IPC mechanisms used to implement computer resource sharing, which is essentially a counter. Semaphores are methods to implement mutually exclusive or shared resource access in a multi-process environment, which can be used to ensure that two or more critical code segments are not called concurrently.

A process/thread must acquire a semaphore before entering a critical code segment; Once the critical piece of code is complete, the process must release the semaphore. Other threads that want to enter the critical code segment must wait until the first process releases the semaphore.

Application form:

  • Mutually exclusive access to a critical resource that can be used by only one process at a time

  • Processing of multiple shared resources, in which the semaphore plays the role of recording the number of idle resources

We can view the semaphores supported by Linux by using kill -l:

2.2. Common semaphores:

code Serial number note
SIGCHLD 17 The parent receives this signal when the child terminates.
SIGQUIT 3 Similar to SIGINT, but controlled by the QUIT character (usually Ctrl-/). A core file is generated when a process exits due to SIGQUIT, which is similar to a program error signal in this sense.
SIGTERM 15 Terminate signals, which, unlike SIGKILL, can be blocked and processed. (It won’t end immediately)
SIGKILL 9 Used to terminate the program immediately. This signal cannot be blocked, processed, or ignored.
SIGHUP 1 This signal is sent when the user terminal connection (normal or abnormal) has ended, usually when the terminal’s control process has ended, to inform individual jobs in the same session that they are no longer associated with the control terminal.
SIGUSR1 10 Leave it to the user
SIGUSR2 12 Leave it to the user
SIGWINCH 28 Ignore signal emitted when the window size changes.

More detailed information can see the blogger article: blog.xujiuming.com/ming/8b4775…

2.3. Semaphore use

In my daily life, I use the kill command to kill a process via PID. In fact, I send a semaphore to the process:

kill-9 Nginx main process PIDCopy the code

As shown in the figure:

Here 9 is the SIGKILL semaphore number. This semaphore is the process that violently kills Nginx and will cause problems if it is currently reading or writing data or performing operations. The recommended semaphore is SIGTERM, which is relatively mild.

We can also see that the SIGKILL signal can only kill the master process, while the worker process still survives. But it is ok if we use a command without -9, the 15 (SIGTERM) semaphore that the kill command sends by default.

Normally, to shut down a process, the system sends the SIGTERM signal first. After a short period of time, the system sends the SIGKILL signal if the process is not shut down.

Nginx and semaphores

Nginx is controlled by signals, such as shutdown, restart, etc. Nginx signal is a mechanism for communication between Nginx processes. The master process controls multiple worker child processes through signals.

3.1. The role of the master process

The master process of nginx is used to manage the master process.

  • Read and verify configuration information

  • Manage worker processes that provide services and send signals to each worker process;

  • Monitor the running status of worker processes. When the worker process exits abnormally, send CHLD signal to the master process, and the master process creates new worker processes to keep the number of worker processes unchanged

It should be noted that the master process does not respond to user requests. What really matters is that the worker process responds to user requests.

3.2. Received semaphore

Then look at the semaphore interfaces of the main and worker processes.

A semaphore role master worker
TERM Termination signal. This is the default signal type sent by the kill command. receive receive
INT Interrupt signal. The effect is the same as when ctrl-C is pressed on the terminal. Close the process directly, regardless of whether the process is being requested receive receive
QUIT Gracefully close the process, waiting for requests to end in the current process. receive receive
HUP Load the new configuration, the master process remains unchanged, and gradually stop the work without requests and start the new worker process receive
USR1 Re-open the log file, log backup, log cutting when used. receive receive
USR2 Used when running nginx processes need to be smoothly upgraded receive
WINCH Gracefully and calmly close worker processes (generally used with USR2) receive receive

3.3. Command lines and semaphores

We are executing nginx commands that send a series of semaphores:

The command A semaphore role
reload HUP Reload the configuration file
reopen USR1 Rereading log files
stop TERM Close quickly, regardless of whether or not a request is being processed
quit QUIT Graceful shutdown, Nginx completes accepted connection requests before exiting

Reload configuration file flow

We know that when we perform nginx -s reload, nginx is not down, so what is the process of reloading the configuration file? Here is an introduction:

  1. Send HUP signal to master (reload command)

  2. Master Checks whether the configuration file is correct

  3. The master process opens the listening port

  4. The master process starts the new worker child process with the new configuration file

  5. The master process sends the QUIT signal to the old worker child process

  6. The old worker process closes the listener handle and closes the process after processing the current connection

Hot deployment process

When an old version of nginx is replaced by a new version of nginx, the nginx service must be cancelled and restarted. If a user is accessing the nginx service, the user will be disconnected, which affects user experience. In this case, hot deployment is required to smooth the replacement.

5.1. Hot Deployment process

The general process is as follows:

  • Replace the old nginx file with the new nginx file

  • Sends the USER2 signal to the master process

  • The master process modifies the PID file and suffixes it with. Oldbin

  • The master process starts the new master process with the new nginx file

  • Send WINCH signal to the old master process, and the old worker child process exits (at this time, the master process does not exit, so as to ensure the rollback in case of error)

  • Rollback case: Send HUP to the old master (according to the old configuration file, pull up the child process), send QUIT to the new master (new offline)

5.2. Hot deployment demonstration

Note: New versions of Nginx require the same directory, version, and configure parameters as older versions.

Step 1: Backup, hot deployment is mainly to replace nginx executable files, to avoid problems, first backup the old nginx binaries.

➜ sbin ll Total usage 23m-rwxrwxr-x 1 molong molong 12M Oct 9 10:55 nginx# new executable
-rwxrwxr-x 1 molong molong 12M Oct 12 15:06 nginx.bak Old executable file

Copy the code

Step 2: Start a new nginx process. Here, the old version of Nginx stops receiving requests by sending SIGUSR2 signals to the running master process (the old version of Nginx) and the new version of Nginx takes over

sudo kill-USR2 Indicates the PID of the main nginx processCopy the code

The execution result is shown as follows:

Nginx. pid and nginx.pid. Oldbin files record the pid of the old and new nginx master processes.

Step 3: Stop the old nginx worker process, but do not stop the old Nginx master process, otherwise it cannot be rolled back

sudo kill-s SIGWINCH Indicates the main PROCESS PID of the old NginxCopy the code

The result is shown below:

At this point, we can verify that the new nginx meets our requirements. If not, we can roll back the process. If yes, we can terminate the old nginx master process.

Kill -s SIGQUIT Main PROCESS PID of the old NginxExit the old nginx master process
Copy the code

5.3. Rollback demo

When it is found that the new nginx does not meet the requirements, a rollback is required. A SIGHUP signal can be sent to the old Nginx master, which will pull up the old configuration file and start the worker child process.

sudo kill-s SIGHUP Main PROCESS PID of old NginxEquivalent to reloading the configuration file
Copy the code

Results:

Then the new Nginx exits the problem.

sudo kill-s SIGQUIT Indicates the main PROCESS PID of the old NginxCopy the code

Results:

Extension: segment error

What is a segment error?

Once an out-of-bounds access occurs in a program, the CPU will generate corresponding protection, resulting in a segmentation fault. According to the above explanation, a segment fault is the access to inaccessible memory.

The memory area is either nonexistent, protected by the system, or may be missing or corrupted.

What are the causes of segment errors?

  • Non-associative null Pointers – this is a special case by memory management hardware

  • Attempted to access a non-existent memory address (in the process’s address space)

  • Programs trying to access memory have no rights (e.g., kernel-structured process context)

  • An attempt to write (a code snippet, for example) to read-only memory.