当前位置: 首页 > 科技观察

深度-为什么Nginx快到停不下来?

时间:2023-03-19 14:03:48 科技观察

Nginx进程模型Nginx服务器,正常运行时:多进程:一个Master进程,多个Worker进程Master进程:管理Worker进程对外接口:接收外部操作(信号)内部转发:根据外部操作Worker通过信号监控管理:监控worker进程的运行状态,worker进程异常终止后自动重启worker进程worker进程:所有worker进程一律平等实际处理:网络请求由worker进程处理;worker进程数:在nginx.conf中配置,一般设置为核心数,以充分利用CPU资源,同时避免进程过多,避免进程争抢CPU资源,增加损失上下文切换。思考:请求连接到Nginx,Master进程负责处理转发?如何选择哪个工作进程来处理请求?请求的处理结果是否还要经过Master进程?HTTP连接建立及请求处理过程Nginx启动时,Master进程加载配置文件Master进程,初始化监听socketMaster进程,fork出多个Worker进程,Worker进程竞争新的连接,获胜方通过一个Socket连接三向握手,并处理请求Nginx高性能,高并发Nginx采用:多进程+异步非阻塞模式(IO多路复用epoll)请求的完整过程:建立连接,读取请求:解析请求的完整流程,processtherequest,responserequest,对应底层,是:读写socket事件Nginx事件处理模型request:Nginx中的http请求。基本HTTPWebServer工作模式:接收请求:逐行读取请求行和请求头,判断该段有请求体后,读取请求体处理请求,返回响应:根据处理结果,生成相应的HTTP请求(响应行、响应头、响应体)Nginx也是同样的套路,整体流程是一样的。模块化架构Nginx的模块按照功能基本可以分为以下几种:事件模块:构建独立于操作系统的事件处理机制框架,提供对特定事件的处理。包括ngx_events_module、ngx_event_core_module和ngx_epoll_module等。nginx使用哪个事件处理模块取决于具体的操作系统和编译选项。phasehandler:这类模块也直接称为handler模??块。主要负责处理客户端请求并生成响应内容,如ngx_http_static_module模块,负责处理客户端的静态页面请求,并准备相应的磁盘文件用于响应内容输出。outputfilter:也称为filter模块,主要负责对输出内容进行处理,可以对输出进行修改。例如,可以实现为所有输出的html页面添加预定义的footbar,或者替换输出图片的URL等工作。upstream:upstream模块实现反向代理的功能,将真正的请求转发给后端服务器,从后端服务器读取响应,返回给客户端。upstream模块是一个特殊的handler,只是响应内容并不是自己实际生成的,而是从后端服务器读取的。load-balancer:负载均衡模块,实现了特定的算法。在众多后端服务器中,选择一台服务器作为某个请求的转发服务器。Nginxvs.Apache网络IO模型常见问题分析:nginx:IO多路复用,epoll(freebsd上的kqueue)高性能,高并发,占用系统资源少apache:阻塞+多进程/多线程更稳定,bug更少,更多模块丰富场景:处理多个请求时,可以使用:IO多路复用或阻塞IO+多线程IO多通道服务:一个线程,跟踪多个socket的状态,读写哪个就绪;阻塞IO+多线程:针对每个请求,新建一个服务线程思考:IO多路复用和多线程的适用场景有哪些?IO多路复用:单连接的请求处理速度没有优势,适合IO密集型场景,事件驱动大并发:只用一个线程处理大量并发请求,减少上下文切换的损耗,并且不需要考虑并发问题,相对可以处理更多的请求;消耗系统资源少(无线程调度开销)适用于长连接的情况(多线程模式的长连接容易造成线程过多,导致频繁调度)阻塞IO+多线程:实现简单,做不依赖于系统调用。适用于CPU密集型场景。每个线程都需要时间和空间。当线程数增加时,线程调度开销呈指数增长。Nginx中的最大连接数。用于处理请求;单个进程的连接数(文件描述符fd)有上限(nofile):ulimit-nNginx上单个worker进程配置的最大连接数:worker_connections上限为nofile配置的worker进程数onNginx:worker_processes因此,Nginx的最大连接数:Nginx的最大连接数:Worker进程数x单个Worker进程的最大连接数。以上是Nginx作为通用服务器时的最大连接数。Nginx作为反向代理服务器时,最大可服务连接数:(worker进程数×单个worker进程最大连接数)/2。当Nginx做反向代理时,会建立一个client连接和一个后端WebServer连接,占用2个连接。思考:为什么每开一个socket占用一个fd?一个进程可以打开的fd数量有限制吗?IO模型场景:处理多个请求时,可以采用:IO多路复用或阻塞IO+多线程IO多路复用:一个线程,跟踪多个socket状态,ready哪个就读哪个就写;阻塞IO+多线程:针对每个请求,新建一个服务线程思考:IO多路复用和多线程的适用场景有哪些?IO多路复用:单连接的请求处理速度没有优势大并发:只用一个线程处理大量并发请求,减少上下文切换的损失,无需考虑并发问题,相对多一些可以处理请求;消耗系统资源少(无线程调度开销)适用于长连接(多线程模式下的长连接容易造成线程过多,调度频繁)阻塞IO+多线程:实现简单,不依赖系统调用。每个线程都需要时间和空间;当线程数增加时,线程调度开销呈指数增长关于select/poll和epoll的更多详细信息,请参考:selectpollepoll三种select/poll系统调用比较://select系统调用intselect(intmaxfdp,fd_set*readfds,fd_set*writefds,fd_set*errorfds,structtimeval*timeout);//轮询系统调用intpoll(structpollfdfds[],nfds_tnfds,inttimeout);select:查询fd_set中是否有就绪的fd,可以设置一个超时时间,当fd(文件描述符)就绪或者超时后返回;fd_set是一组位,编译内核时大小不变,默认大小为1024线性扫描:判断fd是否就绪,需要遍历fd_set的一侧;数据拷贝:用户空间和内核空间,拷贝连接就绪状态信息poll:解决连接数限制:在poll中,将select中的fd_set替换为一个pollfd数组,解决fds数量过少的问题。数据复制:用户空间和内核空间,复制连接就绪状态信息,当就绪时,将fd加入就绪列表。Numberoffds:unlimited(OSlevellimit,单个进程可以打开多少个fds)select,poll,epoll:I/O多路复用机制;I/O多路复用Multiplexing使用一种机制来监视多个描述符,一旦一个描述符就绪(通常是read-ready或write-ready),就可以通知程序执行相应的读写操作。监控多个文件描述符,但select、poll、epoll本质上是同步I/O:用户进程负责读写(从内核空间复制到用户空间),在读写过程中,用户进程被阻塞;异步IO,不需要用户进程负责读写,异步IO会负责从内核空间拷贝到用户空间;Nginx的并发处理能力关于Nginx的并发处理能力:并发连接数,一般经过优化后,峰值可以维持在1~3w左右。(内存和CPU核数不同,会有进一步优化的空间)