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

从底层原理分析Nginx为什么这么快

时间:2023-03-12 16:49:37 科技观察

Nginx进程模型Nginx服务器,正常运行时:多进程:一个Master进程,多个Worker进程Master进程:管理Worker进程外部接口:接收外部操作(信号)内部forwarding:根据不同的外部操作,通过signals管理workermonitoring:监控worker进程的运行状态,worker进程异常终止后自动重启worker进程worker进程:所有worker进程平等实际处理:网络请求,由工人进程;Worker进程数:配置在nginx.conf中,一般设置为核数,充分利用CPU资源,同时避免进程过多,避免进程争抢CPU资源,增加损耗上下文切换。思考:请求连接到Nginx,Master进程负责处理转发?如何选择哪个Worker进程来处理请求?请求的处理结果会不会走Master进程?HTTP连接建立和请求处理过程:Nginx启动时,Master进程,加载配置文件Master进程,初始化监听socket的Master进程,fork出多个Worker进程Worker进程,竞争新的连接。获胜者通过三次握手建立Socket连接并处理请求。Nginx高性能、高并发:Nginx采用:多进程+异步非阻塞模式(IO多路复用epoll)请求的完整过程:建立连接读请求:解析请求、处理请求、响应的完整过程到request,对应底层是:读写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的状态,读写哪个就绪;blockingIO+multi-threading:对于每个请求,创建一个新的服务线程思考:IO多路复用和多线程适用场景?IO多路复用:单连接的请求处理速度没有优势,适用于IO密集型场景,事件驱动大并发:只使用一个线程,处理大量并发请求,减少上下文切换的损失,做不需要考虑并发问题,相对可以处理更多的请求;消耗系统资源少(无线程调度开销)适用于长连接情况(多线程模式下长连接容易导致线程过多,造成频繁调度)阻塞IO+多线程:实现简单,可以不依赖关于系统调用,适用于CPU密集型场景每个线程都需要时间和空间;线程数增加当线程调度开销呈指数增长时,Nginx中的最大连接数是基本背景:Nginx是多进程模型,Worker进程用于处理请求;单个进程的连接数(文件描述符fd)有上限(nofile):Nginx上的ulimit-n配置单个worker进程的最大连接数:worker_connections的上限为nofile配置worker的数量Nginx上的进程数:worker_processes因此,Nginx的最大连接数:Nginx的最大连接数:Worker进程数x单个Worker进程的最大连接数以上是Nginx作为通用服务器使用时,最大连接数Nginx作为反向代理服务器时,可以服务的最大连接数:(Worker进程数×单个Worker进程最大连接数)/2。当Nginx做反向代理时,会建立一个client连接和一个后端WebServer连接,占用2个连接。思路:每个打开的socket占用一个fd。为什么一个进程可以打开的fd数量有限制?IO模型场景:多处理对于每个请求,可以采用:IO多路复用或者阻塞IO+多线程IO多路复用:一个线程,跟踪多个socket的状态,哪个就绪,读写哪个;阻塞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数量过少的问题。数据复制:用户空间和内核空间,复制连接就绪状态信息epoll:event事件驱动事件机制:避免对每个fd进行线性扫描,当fd变为就绪时注册监听事件,设置fd加入就绪列表fd编号:unlimited(OSlevellimit,单个进程可以打开多少个fd)select,poll,epoll:I/O多路复用机制;I/O多路复用是通过一种可以监听多个描述符的机制来完成的,一旦某个描述符就绪(通常是read-ready或者write-ready),就可以通知程序进行相应的读写操作。监控多个文件描述符但select、poll、epoll本质上是同步I/O:用户进程负责读写(从内核空间复制到用户空间),在读写过程中,用户进程被阻塞;异步IO,不需要用户进程负责读写,异步IO会负责从内核空间拷贝到用户空间;Nginx的并发处理能力关于Nginx的并发处理能力:并发连接数,一般优化后,峰值可以维持在1~3w左右。(内存和CPU核数不同,会有进一步优化的空间)