Nginx对自身的定义是轻量级、高性能。在架构上的不同使他可以在高并发的情况依然保持低消耗以及高效的输出。
首先,Nginx在架构上采用了多进程方式,在开启后会同时启用一个Master进程与多个Worker进程。用户通过Master进程来管理其他的Worker进程。Master进程的作用主要用于接收信号以及发送信号给Worker进程,各个平行的Worker进程再接收信号进行处理。如果不修改配置,Worker进程的数量一般只会是1,一般会选择修改配置文件让Worker进程数与逻辑CPU数量匹配,把每个Worker进程分配到不同的CPU上进行处理。
而在事件处理上,相比于Apache传统的阻塞式select模型,Nginx采用了较新的异步非阻塞式epoll网络I/O模型。这样每个Worker进程就可以同时处理上万个请求而保持低消耗。
为何epoll模型可以达到更高效的效果?epoll模型主要采用回调机制,把每个事件的fd(file description)复制并且给予一个回调函数,当设备准备就绪,就采用回调函数来回调事件进行处理。举个例子,你上学发现没带作业,然后告诉你父母来学校给你送作业,select采用的方式是你到传达室一直等到父母把作业送到手里再走,而epoll采用的则是你到传达室写下你的班级以及名字,然后等父母把作业送到的时候传达室会打电话叫你来取,哪个更高效显而易见。
Nginx的模块主要分为五部分:1. 核心模块,2. HTTP模块,3. 邮件模块,4. Stream模块,5. 第三方模块
Nginx的核心模块分为主模块和事件模块两部分。主模块包含Nginx的基本功能,例如配置进程等,而事件模块主要用于控制Nginx处理连接的方式,比如配置epoll、kqueue、select、poll等。像之前所提到过的修改配置文件让Worker数量和逻辑CPU匹配就是通过主模块实现。
首先通过worker_processes设置好Worker进程数量。worker_processes 4;
然后再使用worker_cpu_affinity来设置分别匹配到哪个cpu上。worker_cpu_affinity 0001 0010 0100 1000;
HTTP模块用于处理与HTTP协议有关的事件,而邮件模块则是处理所有跟Mail相关的事件。在Nginx默认的设定中,HTTP模块是被编译进去,因为Nginx主要还是一个HTTP服务器。如果需要编译邮件模块加入入Nginx,则需要在编译时加入选项--with-mail。
Stream模块主要包含了一些和负载均衡以及反向代理相关的模块,其中包括了core、access、limit_conn、proxy、ssl以及upstream。实现服务器的负载均衡以及反向代理则需要通过stream模块的指令。以下是一个简单配置例子:
...upstream test{
server 127.0.01:8080;
server 127.0.01:8081;
}
...server{
listen 80;
server_name localhost;
location / {
proxy_pass http://test;
}
}
...首先利用upstream来设置一个后端服务器组,并且给予这个服务器组一个名字“test”。然后在server下的location里用指令“proxy_pass”来指定要进行反向代理的服务器组,这样在访问localhost的时候会被反向代理到之前在upstream里设置的两个ip地址里进行负载均衡。
Nginx的负载均衡主要分为四种:
1. 轮询
轮询是Nginx默认的负载均衡方式,是把连接给后端服务器一个一个轮着发放。
2. 权重
权重是给后端服务器设定Weight数值,根据数值大小选择发放多少连接。
3. 最少连接
最少连接是把连接发放给后端连接数最少的服务器上。
4. IpHash
IpHash是通过IP地址把每个用户绑定到一个服务器上,这样每次这个用户访问的时候都会连接到这个服务器。
Nginx默认使用的是轮询。如果要加入权重的方式,只需要在设置的后端服务器后加入Weight = …来设定Weight的数值。而最少连接以及IpHash只需要在upstream里面加入指令“least_conn”(最少连接)或者“ip_hash”(IpHash)即可。
在Nginx本身无法满足需求的情况下,很多人选择自主开发Nginx第三方模块。近几年来,Nginx的社区非常活跃,第三方模块层出不穷,现在Nginx已经可以通过很多第三方模块来实现新的功能以及更高效的输出。
比如淘宝开发的第三模块“Ngx_lua”,主要用于将轻便的Lua脚本语言嵌入Nginx中,增强Nginx的能力,开发更加复杂的模块,同时保持异步非阻塞。
在Nginx的上游服务器连接数低的时候,QPS则高。但当连接数提高的时候,QPS则会显著下降。比如当一个上游服务器同时处理60个连接时,QPS可达到8000-9000。但是当连接数达到500时,QPS会降到2000左右。Nginx也有针对这个问题所开发的第三方模块“nginx-limit-upstream”,它可以帮助限制上游服务器的连接数,保持高效的输出。