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

为什么Nginx快到根本停不下来?

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

Nginx是一个免费、开源、高性能的HTTP服务器和反向代理,以及IMAP/POP3代理服务器。图片来自PexelsNginx以其高性能、稳定、丰富的功能、简单的配置和低资源消耗而著称。本文从底层原理分析Nginx为什么这么快!Nginx进程模型Nginx服务器,正常运行时:多进程:一个Master进程,多个Worker进程。主进程:管理工作进程。对外接口:接收外部操作(信号);内部转发:根据不同的外部操作,通过信号管理Worker;监控:监控Worker进程的运行状态,Worker进程异常终止后自动重启Worker进程。工作进程:所有工作进程都是平等的。实际处理:网络请求,由Worker进程处理。NumberofWorkerprocesses:配置在nginx.conf中,一般设置为核心数,以充分利用CPU资源。同时避免进程过多,避免进程争抢CPU资源,增加上下文切换的损失。思考:请求连接到Nginx,Master进程负责处理转发?如何选择哪个Worker进程来处理请求?请求的处理结果会不会走Master进程?HTTP连接建立及请求处理流程HTTP连接建立及请求处理流程如下:Nginx启动时,Master进程加载配置文件。Master进程初始化监听的Socket。Master进程,Fork多个Worker进程。Worker进程竞争新的连接,获胜的一方通过三次握手建立Socket连接并处理请求。Nginx高性能,高并发为什么Nginx具有高性能,可以支持高并发?Nginx采用多进程+异步非阻塞模式(IO多路复用Epoll)。请求的完整流程:建立连接→读取请求→解析请求→处理请求→响应请求。请求的完整过程对应底层:读写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模块,负责处理客户端的静态页面请求,并准备相应的磁盘文件用于响应内容输出。③输出过滤器:也称为过滤模块,主要负责对输出内容进行处理,可以对输出进行修改。例如,可以向所有输出html页面添加预定义的footbar,或者替换输出图像的URL。④upstream:upstream模块实现反向代理的功能,将真正的请求转发给后端服务器,从后端服务器读取响应,返回给客户端。upstream模块是一个特殊的handler,只是响应内容并不是自己实际生成的,而是从后端服务器读取的。⑤load-balancer:负载均衡模块实现了特定的算法。在众多后端服务器中,选择一台服务器作为某个请求的转发服务器。NginxvsApacheNginx常见问题分析:IO多路复用,Epoll(freebsd上的kqueue)高性能高并发占用系统资源少Apache:阻塞+多进程/多线程更稳定,bug少模块多参考文章:http://www.oschina.net/translate/nginx-vs-apachehttps://www.zhihu.com/question/19571087Nginx最大连接数基本背景:Nginx是多进程模型,Worker进程用于处理请求.单个进程的连接数(文件描述符fd),上限(nofile):ulimit-n。Nginx配置单个Worker进程的最大连接数:worker_connections上限为nofile。配置Nginx的Worker进程数:worker_processes。因此,Nginx的最大连接数:Nginx的最大连接数:Worker进程数x单个Worker进程的最大连接数。以上是Nginx作为通用服务器时的最大连接数。Nginx作为反向代理服务器时,最大可服务连接数:(Worker进程数×单个Worker进程最大连接数)/2。Nginx作为反向代理时,会在Client和后端WebServer之间建立连接,占用2个连接。思考:每个打开的Socket占用一个fd?为什么一个进程可以打开的fd数量有限制?HTTP请求与响应HTTP请求:请求行:方法、uri、http版本请求头请求体HTTP响应:响应行:http版本、状态码响应头响应体IO模型处理多个请求时,可以使用:IO多路复用或阻塞IO+multithreading:IO多路复用:一个线程,跟踪多个Socket状态,哪个就绪,读哪个就写哪个。阻塞IO+多线程:对于每一个请求,新建一个服务线程。IO多路复用和多线程的适用场景有哪些?IO多路复用:单连接的请求处理速度没有优势。并发量大:只用一个线程处理大量并发请求,减少上下文切换的损失,不需要考虑并发问题,相对可以处理更多的请求。消耗更少的系统资源(无线程调度开销)。适用于长连接的情况(多线程模式下的长连接容易造成线程过多,导致频繁调度)。阻塞IO+多线程:实现简单,不依赖系统调用。每个线程都需要时间和空间。随着线程数量的增长,线程调度开销呈指数级增长。select/poll与epoll的对比如下:详见:https://www.cnblogs.com/wiessharling/p/4106295.htmlselect/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是一个bitset,编译内核时大小不变,默认大小为1024。特点:连接数有限,fd_set能表示的fd数量太少;线性扫描:判断fd是否就绪,需要遍历fd_set的一侧;数据复制:用户空间和内核空间,复制连接就绪状态信息。poll:解决连接限制:在poll中,将select中的fd_set换成一个pollfd数组,解决fd数量过少的问题。数据复制:用户空间和内核空间,复制连接就绪信息。epoll,event事件驱动:事件机制:避免线性扫描,为每个fd注册一个监听事件,当fd变为就绪时将fd加入就绪列表。Numberoffds:Unlimited(操作系统级别限制,单个进程可以打开多少个fds)。select、poll、epoll:I/O多路复用机制。I/O多路复用使用一种机制来监视多个描述符。一旦一个描述符就绪(通常是读就绪或写就绪),它就可以通知程序执行相应的读写操作;监控多个文件描述符。但select、poll、epoll本质上是同步I/O:用户进程负责读写(从内核空间拷贝到用户空间)。读写过程中,用户进程被阻塞;异步IO不需要用户进程负责读写,异步IO,会负责从内核空间拷贝到用户空间。Nginx的并发处理能力关于Nginx的并发处理能力:并发连接数,一般优化后,峰值可以维持在1~3w左右。(内存和CPU核数不同,会有进一步优化的空间)