Home Operation and Maintenance Nginx How to solve nginx panic group problem

How to solve nginx panic group problem

May 17, 2023 pm 08:49 PM
nginx

1. Solution

When each worker process is created, the ngx_worker_process_init() method will be called to initialize the current worker process. There is a very important point in this process. Step, that is, each worker process will call the epoll_create() method to create a unique epoll handle for itself. For each port that needs to be monitored, there is a file descriptor corresponding to it, and the worker process only adds the file descriptor to the epoll handle of the current process through the epoll_ctl() method and listens to the accept event. Triggered by the client's connection establishment event to handle the event. It can also be seen from here that if the worker process does not add the file descriptor corresponding to the port that needs to be monitored to the epoll handle of the process, then the corresponding event cannot be triggered. Based on this principle, nginx uses a shared lock to control whether the current process has the permission to add the port that needs to be monitored to the epoll handle of the current process. In other words, only the process that acquires the lock will listen to the target port. In this way, it is guaranteed that only one worker process will be triggered each time an event occurs. The following figure is a schematic diagram of the work cycle of the worker process:

How to solve nginx panic group problem

Regarding the process in the figure, one thing that needs to be explained is that each worker process enters the cycle. It will try to acquire the shared lock. If it is not acquired, the file descriptor of the monitored port will be removed from the epoll handle of the current process (it will be removed even if it does not exist). The main purpose of this is to prevent loss. Client connection events, although this may cause a small amount of thundering herd problems, are not serious. Just imagine, if according to theory, the file descriptor of the listening port is removed from the epoll handle when the current process releases the lock, then before the next worker process acquires the lock, the file descriptor corresponding to each port during this period is If there is no epoll handle to listen, the event will be lost. If, on the other hand, the monitored file descriptors are removed only when the lock acquisition fails, as shown in the figure. Since the lock acquisition fails, it means that there must be a process currently monitoring these file descriptors, so it is safe to remove them at this time. of. But one problem this will cause is that, according to the above figure, when the current process completes the execution of a loop, it will release the lock and then handle other events. Note that it does not release the monitored file descriptor during this process. At this time, if another process acquires the lock and monitors the file descriptor, then there are two processes monitoring the file descriptor at this time. Therefore, if a connection establishment event occurs on the client, two workers will be triggered. process. This problem is tolerable for two main reasons:

  1. This kind of thundering herd phenomenon will only trigger a smaller number of worker processes, which is better than waking up all worker processes every time.

  2. The main reason why this kind of panic problem occurs is that the current process releases the lock, but does not release the monitored file descriptor, but the worker process mainly releases the lock after releasing the lock. It is to process the read and write events and check flag bits of the client connection. This process is very short. After the processing is completed, it will try to acquire the lock. At this time, the monitored file descriptor will be released. In comparison, In other words, the worker process that acquires the lock waits longer for processing the client's connection establishment event, so the probability of a thundering herd problem is still relatively small.

2. Source code explanation

The initial event method of the worker process is mainly carried out in the ngx_process_events_and_timers() method. Below we Let’s take a look at how this method handles the entire process. The following is the source code of this method:

void ngx_process_events_and_timers(ngx_cycle_t *cycle) {
 ngx_uint_t flags;
 ngx_msec_t timer, delta;

 if (ngx_trylock_accept_mutex(cycle) == ngx_error) {
  return;
 }

 // 这里开始处理事件,对于kqueue模型,其指向的是ngx_kqueue_process_events()方法,
 // 而对于epoll模型,其指向的是ngx_epoll_process_events()方法
 // 这个方法的主要作用是,在对应的事件模型中获取事件列表,然后将事件添加到ngx_posted_accept_events
 // 队列或者ngx_posted_events队列中
 (void) ngx_process_events(cycle, timer, flags);

 // 这里开始处理accept事件,将其交由ngx_event_accept.c的ngx_event_accept()方法处理;
 ngx_event_process_posted(cycle, &ngx_posted_accept_events);

 // 开始释放锁
 if (ngx_accept_mutex_held) {
  ngx_shmtx_unlock(&ngx_accept_mutex);
 }

 // 如果不需要在事件队列中进行处理,则直接处理该事件
 // 对于事件的处理,如果是accept事件,则将其交由ngx_event_accept.c的ngx_event_accept()方法处理;
 // 如果是读事件,则将其交由ngx_http_request.c的ngx_http_wait_request_handler()方法处理;
 // 对于处理完成的事件,最后会交由ngx_http_request.c的ngx_http_keepalive_handler()方法处理。

 // 这里开始处理除accept事件外的其他事件
 ngx_event_process_posted(cycle, &ngx_posted_events);
}
Copy after login

In the above code, we have omitted most of the checking work, leaving only the skeleton code. First, the worker process will call the ngx_trylock_accept_mutex() method to obtain the lock. If the lock is obtained, it will listen to the file descriptor corresponding to each port. Then the ngx_process_events() method will be called to process the events monitored in the epoll handle. Then the shared lock will be released, and finally the read and write events of the connected client will be processed. Let's take a look at how the ngx_trylock_accept_mutex() method obtains the shared lock:

ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle) {
 // 尝试使用cas算法获取共享锁
 if (ngx_shmtx_trylock(&ngx_accept_mutex)) {

  // ngx_accept_mutex_held为1表示当前进程已经获取到了锁
  if (ngx_accept_mutex_held && ngx_accept_events == 0) {
   return ngx_ok;
  }

  // 这里主要是将当前连接的文件描述符注册到对应事件的队列中,比如kqueue模型的change_list数组
  // nginx在启用各个worker进程的时候,默认情况下,worker进程是会继承master进程所监听的socket句柄的,
  // 这就导致一个问题,就是当某个端口有客户端事件时,就会把监听该端口的进程都给唤醒,
  // 但是只有一个worker进程能够成功处理该事件,而其他的进程被唤醒之后发现事件已经过期,
  // 因而会继续进入等待状态,这种现象称为"惊群"现象。
  // nginx解决惊群现象的方式一方面是通过这里的共享锁的方式,即只有获取到锁的worker进程才能处理
  // 客户端事件,但实际上,worker进程是通过在获取锁的过程中,为当前worker进程重新添加各个端口的监听事件,
  // 而其他worker进程则不会监听。也就是说同一时间只有一个worker进程会监听各个端口,
  // 这样就避免了"惊群"问题。
  // 这里的ngx_enable_accept_events()方法就是为当前进程重新添加各个端口的监听事件的。
  if (ngx_enable_accept_events(cycle) == ngx_error) {
   ngx_shmtx_unlock(&ngx_accept_mutex);
   return ngx_error;
  }

  // 标志当前已经成功获取到了锁
  ngx_accept_events = 0;
  ngx_accept_mutex_held = 1;

  return ngx_ok;
 }

 // 前面获取锁失败了,因而这里需要重置ngx_accept_mutex_held的状态,并且将当前连接的事件给清除掉
 if (ngx_accept_mutex_held) {
  // 如果当前进程的ngx_accept_mutex_held为1,则将其重置为0,并且将当前进程在各个端口上的监听
  // 事件给删除掉
  if (ngx_disable_accept_events(cycle, 0) == ngx_error) {
   return ngx_error;
  }

  ngx_accept_mutex_held = 0;
 }

 return ngx_ok;
}
Copy after login

In the above code, it essentially does three main things:

  1. Pass The ngx_shmtx_trylock() method attempts to use the cas method to obtain the shared lock;

  2. After obtaining the lock, the ngx_enable_accept_events() method is called to listen to the file descriptor corresponding to the target port;

  3. If the lock is not acquired, call the ngx_disable_accept_events() method to release the monitored file descriptor.

The above is the detailed content of How to solve nginx panic group problem. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to check the name of the docker container How to check the name of the docker container Apr 15, 2025 pm 12:21 PM

You can query the Docker container name by following the steps: List all containers (docker ps). Filter the container list (using the grep command). Gets the container name (located in the "NAMES" column).

How to configure nginx in Windows How to configure nginx in Windows Apr 14, 2025 pm 12:57 PM

How to configure Nginx in Windows? Install Nginx and create a virtual host configuration. Modify the main configuration file and include the virtual host configuration. Start or reload Nginx. Test the configuration and view the website. Selectively enable SSL and configure SSL certificates. Selectively set the firewall to allow port 80 and 443 traffic.

How to configure cloud server domain name in nginx How to configure cloud server domain name in nginx Apr 14, 2025 pm 12:18 PM

How to configure an Nginx domain name on a cloud server: Create an A record pointing to the public IP address of the cloud server. Add virtual host blocks in the Nginx configuration file, specifying the listening port, domain name, and website root directory. Restart Nginx to apply the changes. Access the domain name test configuration. Other notes: Install the SSL certificate to enable HTTPS, ensure that the firewall allows port 80 traffic, and wait for DNS resolution to take effect.

How to check whether nginx is started How to check whether nginx is started Apr 14, 2025 pm 01:03 PM

How to confirm whether Nginx is started: 1. Use the command line: systemctl status nginx (Linux/Unix), netstat -ano | findstr 80 (Windows); 2. Check whether port 80 is open; 3. Check the Nginx startup message in the system log; 4. Use third-party tools, such as Nagios, Zabbix, and Icinga.

How to check nginx version How to check nginx version Apr 14, 2025 am 11:57 AM

The methods that can query the Nginx version are: use the nginx -v command; view the version directive in the nginx.conf file; open the Nginx error page and view the page title.

How to create containers for docker How to create containers for docker Apr 15, 2025 pm 12:18 PM

Create a container in Docker: 1. Pull the image: docker pull [mirror name] 2. Create a container: docker run [Options] [mirror name] [Command] 3. Start the container: docker start [Container name]

How to start containers by docker How to start containers by docker Apr 15, 2025 pm 12:27 PM

Docker container startup steps: Pull the container image: Run "docker pull [mirror name]". Create a container: Use "docker create [options] [mirror name] [commands and parameters]". Start the container: Execute "docker start [Container name or ID]". Check container status: Verify that the container is running with "docker ps".

How to start nginx server How to start nginx server Apr 14, 2025 pm 12:27 PM

Starting an Nginx server requires different steps according to different operating systems: Linux/Unix system: Install the Nginx package (for example, using apt-get or yum). Use systemctl to start an Nginx service (for example, sudo systemctl start nginx). Windows system: Download and install Windows binary files. Start Nginx using the nginx.exe executable (for example, nginx.exe -c conf\nginx.conf). No matter which operating system you use, you can access the server IP

See all articles