Nginx 以其高性能,稳定性,丰盛的性能,简略的配置和低资源耗费而闻名。本文从底层原理剖析 Nginx 为什么这么快!
Nginx 的过程模型
Nginx 服务器,失常运行过程中:
多过程:一个 Master 过程、多个 Worker 过程。
Master 过程:治理 Worker 过程。对外接口:接管内部的操作(信号);对内转发:依据内部的操作的不同,通过信号治理 Worker;监控:监控 Worker 过程的运行状态,Worker 过程异样终止后,主动重启 Worker 过程。
Worker 过程:所有 Worker 过程都是平等的。理论解决:网络申请,由 Worker 过程解决。Worker 过程数量:在 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 申请。
根本的 HTTP Web Server 工作模式:
接管申请:逐行读取申请行和申请头,判断段有申请体后,读取申请体。
解决申请。
返回响应:依据处理结果,生成相应的 HTTP 申请(响应行、响应头、响应体)。
Nginx 也是这个套路,整体流程统一:
模块化体系结构
更多 Linux 服务器开发底层原理知识点 Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,P2P,线程池,Docker,TCP/IP,协程,DPDK,Linux 内核内容。+602878196(VX 同号)获取
—
Nginx 的模块依据其性能基本上能够分为以下几种类型:
①event module:搭建了独立于操作系统的事件处理机制的框架,及提供了各具体事件的解决。包含 ngx_events_module,ngx_event_core_module 和 ngx_epoll_module 等。
Nginx 具体应用何种事件处理模块,这依赖于具体的操作系统和编译选项。
②phase handler:此类型的模块也被间接称为 handler 模块。次要负责解决客户端申请并产生待响应内容,比方 ngx_http_static_module 模块,负责客户端的动态页面申请解决并将对应的磁盘文件筹备为响应内容输入。
③output filter:也称为 filter 模块,次要是负责对输入的内容进行解决,能够对输入进行批改。
例如,能够实现对输入的所有 html 页面减少预约义的 footbar 一类的工作,或者对输入的图片的 URL 进行替换之类的工作。
④upstream:upstream 模块实现反向代理的性能,将真正的申请转发到后端服务器上,并从后端服务器上读取响应,发回客户端。
upstream 模块是一种非凡的 handler,只不过响应内容不是真正由本人产生的,而是从后端服务器上读取的。
⑤load-balancer:负载平衡模块,实现特定的算法,在泛滥的后端服务器中,抉择一个服务器进去作为某个申请的转发服务器。
常见问题分析
Nginx vs Apache
Nginx:
IO 多路复用,Epoll(freebsd 上是 kqueue)
高性能
高并发
占用系统资源少
Apache:
阻塞 + 多过程 / 多线程
更稳固,Bug 少
模块更丰盛
Nginx 最大连接数
根底背景:
Nginx 是多过程模型,Worker 过程用于解决申请。
单个过程的连接数(文件描述符 fd),有下限(nofile):ulimit -n。
Nginx 上配置单个 Worker 过程的最大连接数:worker_connections 下限为 nofile。
Nginx 上配置 Worker 过程的数量:worker_processes。
因而,Nginx 的最大连接数:
Nginx 的最大连接数:Worker 过程数量 x 单个 Worker 过程的最大连接数。
下面是 Nginx 作为通用服务器时,最大的连接数。
Nginx 作为反向代理服务器时,可能服务的最大连接数:(Worker 过程数量 x 单个 Worker 过程的最大连接数)/ 2。
Nginx 反向代理时,会建设 Client 的连贯和后端 Web Server 的连贯,占用 2 个连贯。
思考:
每关上一个 Socket 占用一个 fd?
为什么,一个过程可能关上的 fd 数量有限度?
HTTP 申请和响应
HTTP 申请:
申请行:method、uri、http version
申请头
申请体
HTTP 响应:
响应行:http version、status code
响应头
响应体
IO 模型
解决多个申请时,能够采纳:IO 多路复用或者阻塞 IO+ 多线程:
IO 多路复用:一个线程,跟踪多个 Socket 状态,哪个就绪,就读写哪个。
阻塞 IO+ 多线程:每一个申请,新建一个服务线程。
IO 多路复用和多线程的实用场景?
IO 多路复用:单个连贯的申请处理速度没有劣势。
大并发量:只应用一个线程,解决大量的并发申请,升高上下文环境切换损耗,也不须要思考并发问题,绝对能够解决更多的申请。
耗费更少的系统资源(不须要线程调度开销)。
实用于长连贯的状况(多线程模式长连贯容易造成线程过多,造成频繁调度)。
阻塞 IO + 多线程:实现简略,能够不依赖零碎调用。
每个线程,都须要工夫和空间。
线程数量增长时,线程调度开销指数增长。
select/poll 和 epoll 比拟如下:
select/poll 零碎调用:
// select 零碎调用
int select(int maxfdp,fd_set readfds,fd_set writefds,fd_set errorfds,struct timeval timeout);
// poll 零碎调用
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
select:
查问 fd_set 中,是否有就绪的 fd,能够设定一个超时工夫,当有 fd (File descripter) 就绪或超时返回。
fd_set 是一个位汇合,大小是在编译内核时的常量,默认大小为 1024。
特点:连接数限度,fd_set 可示意的 fd 数量太小了;线性扫描:判断 fd 是否就绪,须要遍历一边 fd_set;数据复制:用户空间和内核空间,复制连贯就绪状态信息。
poll:
解决了连接数限度:poll 中将 select 中的 fd_set 替换成了一个 pollfd 数组,解决 fd 数量过小的问题。
数据复制:用户空间和内核空间,复制连贯就绪状态信息。
epoll,event 事件驱动:
事件机制:防止线性扫描,为每个 fd,注册一个监听事件,fd 变更为就绪时,将 fd 增加到就绪链表。
fd 数量:无限度(OS 级别的限度,单个过程能关上多少个 fd)。
select,poll,epoll:
I/O 多路复用的机制。
I/O 多路复用就通过一种机制,能够监督多个描述符,一旦某个描述符就绪(个别是读就绪或者写就绪),可能告诉程序进行相应的读写操作;监督多个文件描述符。
但 select,poll,epoll 实质上都是同步 I/O:用户过程负责读写(从内核空间拷贝到用户空间),读写过程中,用户过程是阻塞的;异步 IO,无需用户过程负责读写,异步 IO,会负责从内核空间拷贝到用户空间。
Nginx 的并发解决能力
对于 Nginx 的并发解决能力:并发连接数,个别优化后,峰值能放弃在 1~3w 左右。(内存和 CPU 外围数不同,会有进一步优化空间)。