本篇博客围绕Nginx基本原理、优化配置、配置文件,详细解释。
经常用Nginx,这些基本常识您知道多少呢?感兴趣的可以跟小编一块来学习呀。
目录
1、Nginx占用进程
使用这个命令可以查看Nginx运行期间占用的进程。从这里可以发现Nginx占用了两个进程,分别是mater
和 worker
。
ps -ef | grep nginx
![](https://img-blog.csdnimg.cn/e8f7866262204f2eaa4a6da42df71c4f.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjEwMTgzOQ==,size_16,color_FFFFFF,t_60)
![](https://img-blog.csdnimg.cn/cdd1755864bc4795a2c78c3cdf7f405c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjEwMTgzOQ==,size_16,color_FFFFFF,t_60)
2、worker 如何进行工作的
![](https://img-blog.csdnimg.cn/eb12f27fd7a24357a5f4556f757263c1.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjEwMTgzOQ==,size_16,color_FFFFFF,t_60)
1.在nginx启动后,会有一个master进程和多个worker进程,master进程主要用来管理worker进程,包括:接受信号,将信号分发给worker进程,监听worker进程工作状态,当worker进程退出时(非正常),启动新的worker进程。基本的网络事件会交给worker进程处理。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的 。一个请求,只可能在一个worker进程中处理
,一个worker进程,不可能处理其它进程的请求
。
2.当master接收到重新加载的信号会怎么处理(./nginx -s reload)?,master会重新加载配置文件,然后启动新的进程,使用的新的worker进程来接受请求,并告诉老的worker进程他们可以退休了,老的worker进程将不会接受新的,老的worker进程处理完手中正在处理的请求就会退出。
3.worker进程是如何处理用户的请求呢?首先master会根据配置文件生成一个监听相应端口的socket,然后再faster出多个worker进程,这样每个worker就可以接受从socket过来的消息(其实这个时候应该是每一个worker都有一个socket,只是这些socket监听的地址是一样的
)。当一个连接过来的时候,每一个worker都能接收到通知,但是只有一个worker能和这个连接建立关系,其他的worker都会连接失败,这就是所谓的惊群现在,为了解决这个问题,nginx提供一个共享锁accept_mutex
,有了这个共享锁后,就会只有一个worker去接收这个连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。
3、一个 master 和多个 woker 有好处
(1)可以使用 nginx –s reload 热部署,利用 nginx 进行热部署操作
(2)每个 woker 是独立的进程,如果有其中的一个 woker 出现问题,其他 woker 独立的,继续进行争抢,实现请求过程,不会造成服务中断
4、设置多少个 woker 合适
worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的 。
worker_processes是在配置文件当中全局块配置的。
查看CPU个数:cat /proc/cpuinfo |grep "cores"|uniq
比如查到结果是 cpu cores : 4
就在Nginx配置文件当中修改worker_processes,他默认值是1。
worker_processes 4;
5、worker_cpu_affinity指定CPU
worker_cpu_affinity
配置来绑定 CPU 内核
为什么要绑定 worker 进程到指定的 CPU 内核呢 ?
nginx默认是没有开启利用多核cpu的配置的
。需要通过增加worker_cpu_affinity配置参数来充分利用多核cpu,cpu是任务处理,当计算最费时的资源的时候,cpu核使用上的越多,性能就越好。
假定每一个 worker 进程都是非常繁忙 的 , 如果多个 worker 进程都在抢同一个 CPU , 那么这就会出现同步问题 。 反之 , 如果每一 个 worker 进程都独享一个 CPU , 就在内核的调度策略上实现了完全的并发。
示例一:2核cpu,开启2个进程
worker_processes 2;
worker_cpu_affinity 01 10;
解释:01表示启用第一个CPU内核,10表示启用第二个CPU内核worker_cpu_affinity 01 10;表示开启两个进程,第一个进程对应着第一个CPU内核,第二个进程对应着第二个CPU内核。
示例二:2核cpu,开启4个进程
开启了四个进程,它们分别对应着开启2个CPU内核
worker_processes 4;
worker_cpu_affinity 01 10 01 10;
示例三:4个cpu,开启4个进程
解释:0001表示启用第一个CPU内核,0010表示启用第二个CPU内核,0100启用第三个CPU内核,依此类推。。。
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
示例四:4核cpu,开启2个进程
worker_processes 2;
worker_cpu_affinity 0101 1010;
解释:0101表示开启第一个和第三个内核,1010表示开启第二个和第四个内核;2个进程对应着四个内核;worker_cpu_affinity配置是写在/etc/nginx/nginx.conf里面的;2核是 01,四核是0001,8核是00000001,有多少个核,就有几位数,1表示该内核开启,0表示该内核关闭。
示例五:8核cpu,开启8个进程
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
解释:0001表示启用第一个CPU内核,0010表示启用第二个CPU内核,依此类推;worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。
配置完之后可以重启nginx,用ab工具或者wrk工具,可以进行性能测试,在服务器上执行top,然后按1,就可以看到cpu工作情况,如果多个cpu内核的利用率差不多,就证明nginx已经成功利用了多核cpu,测试结束后,cpu内核的负载都同时降低。
6、连接数 worker_connection
worker_connection是在配置文件events块配置的。
第一个:发送请求,占用了 woker 的几个连接数?
答案:2 或者 4 个
还是以这张图为例,假如我们不访问tomcat,只是利用Nginx取静态资源,那么他会先由worker接受请求,这是一个连接,然后拿到数据响应给客户端,这又是一个连接,一共两个连接。
假如需要访问tomcat,那就是4个连接。也就意味着一个请求,需要占用Nginx的4个连接。
7、并发值怎么算
每个 woker 支持最大的连接数 1024。
普通的静态访问最大并发数是: worker_connections(work最大连接数) * worker_processes(work数量) /2
,
如果是 HTTP 作 为反向代理来说,最大并发数量应该是 worker_connections * worker_processes/4
。
举例:一个一核服务器,安装了Nginx,然后设置了最大连接数1024,访问静态资源最大支持的并发量是512。假如是取tomcat,那就是206并发数。
8、nginx的事件驱动机制
为什么几个worker进程(每一个worker进程里面其实只有一个主线程)能同时接收上万的请求呢?
这是因为nginx事件处理机制是异步非阻塞的
。nginx将一个请求划分为多个阶段来异步处理模块,每个阶段只是处理请求的一部分,如果请求的这一部分发生阻塞,nginx不会等待,它会处理其他的请求的某一部分。
传统web服务器的每个事件消费者独占一个进程(线程)资源,这种情况对于用户规模较小的情况来说,用户响应速度快,但是当并发规模达到数十万上百万的时候,由于线程(进程)数目过多,会频繁的切换,而且当线程阻塞的时候会进行睡眠,也会造成资源的浪费,这样服务器就会产生瓶颈.
nginx服务器采用的事件驱动机制不同,他不会为每个消费事件创建一个进程或线程,这样就不会产生由于进程间频繁切换占用cpu而产生的瓶颈,而且nginx不会让事件阻塞,即采用无阻塞事件驱动模型,这样就不会因为事件阻塞使进程睡眠而造成的资源浪费.
事件发生源产生事件->事件收集器来收集分发事件(选择自己感兴趣的)->消费事件.
9、Nginx配置文件结构
nginx文件结构
... #全局块
events { #events块
...
}
http #http块
{
... #http全局块
server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN]
{
...
}
}
server
{
...
}
... #http全局块
}
1、全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
2、events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
3、http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
4、server块:配置虚拟主机的相关参数,一个http中可以有多个server。
5、location块:配置请求的路由,以及各种页面的处理情况。
########### 每个指令必须有分号结束。#################
#user administrator administrators; #配置用户或者组,默认为nobody nobody。
#worker_processes 2; #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid; #指定nginx进程运行文件存放地址
error_log log/error.log debug; #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
#use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
worker_connections 1024; #最大连接数,默认为512
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
access_log log/access.log myFormat; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。
upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
error_page 404 https://www.baidu.com; #错误页
server {
keepalive_requests 120; #单连接请求上限次数。
listen 4545; #监听端口
server_name 127.0.0.1; #监听地址
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index vv.txt; #设置默认页
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
}
}
上面是nginx的基本配置,需要注意的有以下几点:
1、log_format格式:
$remote_addr
与$http_x_forwarded_for
用以记录客户端的ip地址;$remote_user
:用来记录客户端用户名称;$time_local
: 用来记录访问时间与时区;$request
: 用来记录请求的url与http协议;$status
: 用来记录请求状态;成功是200,$body_bytes_s ent
:记录发送给客户端文件主体内容大小;$http_referer
:用来记录从那个页面链接访问过来的;$http_user_agent
:记录客户端浏览器的相关信息;
2、惊群现象:一个网路连接到来,多个睡眠的进程被同事叫醒,但只有一个进程能获得链接,这样会影响系统性能。
3、每个指令必须有分号结束。