nginx关于并发的总结

一、环境

1.nginx版本

[root@node4 ~]# nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
configure arguments: --prefix=/usr/local/nginx

2.操作系统

centos7

3.硬件配置

[root@node2 ~]# cat /proc/cpuinfo |grep process
processor	: 0
processor	: 1
processor	: 2
processor	: 3

[root@node2 ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           3.8G        446M        3.0G         12M        409M        3.1G
Swap:          1.5G          0B        1.5G

二、nginx配置

nginx 地址为192.168.1.18,其他地址为客户端

1.默认配置

# nginx 启动一个work进程来处理请求
worker_processes  1;

events {
	# 一个work进程同时并发处理1024个请求
    worker_connections  1024;
}

查看 worker process 进程是master process 的子进程

[root@node4 ~]# ps -lef |grep nginx |grep -v "grep"
1 S root      11250      1  0  80   0 -  5141 sigsus 01:35 ?        00:00:00 nginx: master process nginx
5 S nobody    11251  11250  0  80   0 -  5247 ep_pol 01:35 ?        00:00:00 nginx: worker process

2.worker_connections

通过修改配置来理解worker_connections配置的真正含义

2.1 修改为1

events {
    worker_connections  1;
}

语法测试直接报错:

[root@node4 conf]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: [emerg] 1 worker_connections are not enough for 1 listening sockets
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed

2.2 修改为2

检测没有问题

[root@node4 conf]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
2.2.1 使用telnet访问

使用telnet访问发现 服务端直接断开了。

[root@node4 ~]# netstat -antp |grep 80 -w
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.1:64782       TIME_WAIT   - 
2.2.2 使用浏览器访问

发现浏览器无法返回网页内容,并且服务端出现了较多的TIME_WAIT.这是因为浏览器自己在不断的请求web服务器。(重试)
服务器又没有可用的连接,所以在不断的断开和重置连接,所有出现了大量的TIME_WAIT

[root@node4 ~]# netstat -antp |grep 80 -w
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.1:64910       TIME_WAIT   -                   
tcp        0      0 192.168.1.18:80         192.168.1.1:64911       TIME_WAIT   -                   
tcp        0      0 192.168.1.18:80         192.168.1.1:64906       TIME_WAIT   -                   
tcp        0      0 192.168.1.18:80         192.168.1.1:64918       TIME_WAIT   -                   
tcp        0      0 192.168.1.18:80         192.168.1.1:64920       FIN_WAIT2   -                   
tcp        0      0 192.168.1.18:80         192.168.1.1:64908       TIME_WAIT   -                   
tcp        0      0 192.168.1.18:80         192.168.1.1:64904       TIME_WAIT   - 

nginx 错误日志中也出现大量的错误信息,如下:

2024/05/10 03:11:33 [alert] 11691#0: 2 worker_connections are not enough

2.3 修改为3

修改为3的时候,日志中不在报错。

2.3.1 使用telnet访问

这里使用两个不同的client 分别为192.168.1.16和192.168.1.20

1.先在1.16 访问nginx

[root@node4 logs]# netstat -antp |grep 80 -w 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.16:56006      ESTABLISHED 13508/nginx: worker

2.在使用1.20 访问nginx

[root@node4 logs]# netstat -antp |grep 80 -w 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.20:55248      ESTABLISHED 13508/nginx: worker 
tcp        0      0 192.168.1.18:80         192.168.1.16:56012      TIME_WAIT   - 

此时发现当1.20 连接上来的时候 1.16的连接被断开了。

2.3.2 使用浏览器访问

浏览器访问一次 会连接过来两次请求。

[root@node4 logs]# netstat -antp |grep 80 -w 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.1:54287       ESTABLISHED 13508/nginx: worker 
tcp        0      0 192.168.1.18:80         192.168.1.1:54286       TIME_WAIT   - 

当修改为3的时候,说明worker进程只能接收一个请求

2.4 修改为4

这时候发现两个请求过来没有问题

[root@node4 conf]# netstat -antp |grep -w 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.20:55294      ESTABLISHED 13908/nginx: worker 
tcp        0      0 192.168.1.18:80         192.168.1.16:56040      ESTABLISHED 13908/nginx: worker

在加一个请求,发现原来的请求就断开了

[root@node4 conf]# netstat -antp |grep -w 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11538/nginx: master 
tcp        0      0 192.168.1.18:80         192.168.1.20:55294      ESTABLISHED 13908/nginx: worker 
tcp        0      0 192.168.1.18:80         192.168.1.16:56040      TIME_WAIT   -                   
tcp        0      0 192.168.1.18:80         192.168.1.16:56042      ESTABLISHED 13908/nginx: worker 

2.5 结论

目前来看,worker_connections的连接数量是 值 - 2 是真正的连接数量

3.提高并发量500

3.1 修改为500

worker_connections  500;

3.2 批量建立请求

使用telnet批量进行请求

for i in {1..500};do telnet  192.168.1.18 80 & done

3.3 查看结果

可以看出建立了468个连接

[root@node4 ~]# ss -s
Total: 1026 (kernel 2796)
TCP:   508 (estab 471, closed 32, orphaned 0, synrecv 0, timewait 32/0), ports 0

这里手动统计发现468个连接,但是断开了32个连接。发现这个32连接都是 "FIN_WAIT2"状态的连接。
nginx的错误日志中也没有报错。

[root@node4 ~]# netstat -anpt |grep -w 80 |grep -i estab |wc -l
468
[root@node4 ~]# netstat -anpt |grep -w 80 |grep -i wait |wc -l
32

4.提高并发量1024

此时发现nginx的并发已经并占满了。但是在3中为什么有32个tw连接,暂时还不太清楚

[root@node2 conf]# ss -s
Total: 2418 (kernel 2856)
TCP:   1047 (estab 1028, closed 1, orphaned 0, synrecv 0, timewait 0/0), ports 0

Transport Total     IP        IPv6
*	  2856      -         -        
RAW	  1         0         1        
UDP	  10        7         3        
TCP	  1046      1038      8        
INET	  1057      1045      12       
FRAG	  0         0         0 

手动验证

[root@node2 ~]# netstat -anpt |grep -w 80 |grep -i estab |wc -l
1024

4.1 报错

此时发现日志开始报错,打开的文件太多了。

2024/05/12 16:13:55 [crit] 4736#0: accept4() failed (24: Too many open files)

为了解决当前报错,和以上nginx 接受请求要少两个连接的迷惑,这里要讲一下 “文件描述符”.见 “三 文件描述符号”

4.2 文件描述符限制

发现系统限制了单个进程打开文件描述的限制

[root@node2 ~]# ulimit -n
1024

4.3 查看进程描述符数量

[root@node2 ~]# ps aux |grep nginx
root       3403  0.0  0.0  20604  1408 ?        Ss   14:44   0:00 nginx: master process nginx
nobody     4736  0.0  0.0  23100  1760 ?        S    16:09   0:00 nginx: worker process

[root@node2 ~]# cd /proc/4736/fd
[root@node2 fd]# ls |wc -l
1024

这里发现文件描述数量直接到达了文件系统的限制.

4.4 修改值

ulimit -n 10240

4.5 再次请求

发现错误日志中不在报错。

5.nginx打开文件限制

nginx 中也有参数限制了nginx打开文件的数量。

worker_processes  2;

# 此参数就是控制单个进程打开系统文件的数量
worker_rlimit_nofile 100;


events {
    worker_connections  4096;
}

有时候,系统的ulimit -n的值已经提高,但是nginx中依然报打开文件太多的错误。并发量也上不去。就是这个值太小。这个值配置文件中默认是没有的。需要手动添加

6.keepalive_requests

keepalive_requests指令用于设置一个keep-alive连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭。默认是100。
是指一个keep alive建立之后,nginx就会为这个连接设置一个计数器,记录这个keep alive的长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时,则nginx会强行关闭这个长连接,逼迫客户端不得不重新建立新的长连接。

6.1 测试配置

当用户请求3次之后,然后断开连接原链接,客户端会重新请求。

http {
	......
    keepalive_timeout  65;
    keepalive_requests 3;
    ......

}

6.1 请求建立连接

使用浏览器的无痕模式访问

#这是第一次建立连接
[root@node4 conf]# netstat -antp |grep 80 -w
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1784/nginx: master  
tcp        0      0 192.168.1.18:80         192.168.1.1:62952       ESTABLISHED 4122/nginx: worker  

# 第二次
[root@node4 conf]# netstat -antp |grep 80 -w
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1784/nginx: master  
tcp        0      0 192.168.1.18:80         192.168.1.1:62952       ESTABLISHED 4122/nginx: worker  

# 第三次断开
[root@node4 conf]# netstat -antp |grep 80 -w
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1784/nginx: master  
tcp        0      0 192.168.1.18:80         192.168.1.1:62952       TIME_WAIT   - 

三、文件描述符

1.概念

在linux系统中,“文件描述符” 是一个非负"整数".

2.作用

当进程使用open函数打开一个文件时,open函数返回的值就是 “文件描述符”。进程可以通过文件描述符对文件进行操作。
每一个进程在启动时候,都会产生3个默认的文件描述符 0,1,2.懂的都懂

3.程序验证

这里使用程序验证一下

[root@node4 ~]# cat a.py 
import time,os

# 这里先打印程序的PID
print("pid = {}".format(os.getpid()))
time.sleep(20)

# 打开两个文件,然后返回两个文件描述符
with open('/root/t1','a')as f1,open('/root/t2','a') as f2:
  print('f1 = {},f2 = {}'.format(f1.fileno(),f2.fileno()))
  f1.write("hello")
  f2.write("hello")
  time.sleep(10)


print('--------------')
# 这里等待100是为了 验证with 函数会自动关闭文件,然后文件描述符消息
time.sleep(100)

3.1 默认文件描述符

查看进程默认的文件描述符.

[root@node4 ~]# cd /proc/13146/fd
[root@node4 fd]# ll
total 0
lrwx------. 1 root root 64 May 12 20:19 0 -> /dev/pts/0
lrwx------. 1 root root 64 May 12 20:19 1 -> /dev/pts/0
lrwx------. 1 root root 64 May 12 20:19 2 -> /dev/pts/0

3.2 生成的文件描述符

[root@node4 fd]# ll
total 0
lrwx------. 1 root root 64 May 12 20:19 0 -> /dev/pts/0
lrwx------. 1 root root 64 May 12 20:19 1 -> /dev/pts/0
lrwx------. 1 root root 64 May 12 20:19 2 -> /dev/pts/0

# 这里生成了两个新的文件描述符,和程序中打印的文件描述符号一致
l-wx------. 1 root root 64 May 12 20:19 3 -> /root/t1
l-wx------. 1 root root 64 May 12 20:19 4 -> /root/t2

4.打开文件的限制

4.1 系统限制

linux系统能够打开的文件数量也是有限的,通过以下命令查看

[root@node2 ~]# cat /proc/sys/fs/file-max 
394628

或者
[root@node2 ~]# sysctl -a |grep -i fs.file-max
fs.file-max = 394628

4.2 进程限制

系统对每个进程打开的文件数量也进行了限制。

[root@node2 ~]# ulimit -a |grep open
open files                      (-n) 1024

或者
[root@node2 ~]# ulimit  -n
1024

5.修改ulimit值

5.1 临时修改

重启服务器后配置失效

[root@node2 ~]# ulimit -n 10240
[root@node2 ~]# ulimit -n
10240

5.2 永久修改

vim /etc/security/limits.conf

#打开文件的软限制
*	soft	nofile	10240

#打开文件的硬限制
*	hard	nofile	10240

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Nginx实现高并发的主要原因是其采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。Nginx的架构设计使得它能够高效地处理并发连接和请求。具体来说,Nginx采用了以下几种方式来实现高并发: 1. 模块化设计:Nginx采用高度模块化的设计,将服务器分解为多个功能模块,每个模块只负责自身的功能,严格遵循“高内聚,低耦合”的原则。这种设计使得Nginx能够灵活地扩展和定制功能,同时也提高了并发处理的效率。\[2\] 2. 事件驱动和异步处理:Nginx使用事件驱动的机制来处理连接请求,每个连接请求由少数几个仅包含一个线程的进程worker以高效的回环机制进行处理。这种异步处理方式使得Nginx能够同时处理数千个并发连接和请求,提高了并发处理的能力。\[1\] 3. 多路复用和事件通知机制:Nginx采用了多路复用和事件通知机制,通过少量的线程和进程来处理大量的并发连接和请求。多路复用技术可以同时监控多个连接的状态,当有事件发生时,通过事件通知机制将事件传递给相应的处理程序,从而实现高效的并发处理。\[1\] 总结起来,Nginx实现高并发的关键在于其模块化、事件驱动、异步、单线程及非阻塞的架构设计,以及多路复用和事件通知机制的应用。这些特点使得Nginx能够高效地处理大量的并发连接和请求,提供稳定性和高性能的服务。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* [Nginx并发实现原理学习](https://blog.csdn.net/qq_45808700/article/details/128710270)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [面试题:Nginx 是如何实现高并发?常见的优化手段有哪些?](https://blog.csdn.net/weixin_33826268/article/details/91399333)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值