前言
nginx[enginex]是一个HTTP和反向代理服务器、一个邮件代理服务器和一个通用的TCP/UDP代理服务器。以轻量级、高性能而受众颇多。
nginx配置的构成
nginx的结构由三大部分组成:全局部分、events、http。
全局部分
全局部分可以配置:
运行nginx用户的用户或者用户组
nginx的进程数,
nginx错误日志的存放路径、
Nginx进程PID存放路径
worker_rlimit_nofile,指定进程可以打开的最多文件描述数目,理论值应该是最多打开文件数(ulimit -n )与nginx进程数相除,但是Nginx分配请求并不是那么均匀,所以最好与 ulimit -n 的值保持一致。
现在在Linux内核下开启文件打开数为65535,worker_rlimit_nofile 就相应应该填写65535.这是因为Nginx调度时请求到进程并不是那么均衡,所以假如填 写10240,总并发量达到3-4万时就有进程超过10240了,这就会返回502。
如:worker_rlimit_nofile 65535; 用来绑定worker进程和CPU,Linux内核2.4 以上可用
event模块
1、use epoll.事件处理模型的配置。用来指定Nginx的工作模式。Nginx支持的工作模式有select、poll、kqueue、epoll、rtsig和/dev/poll 。其中select 和poll 都 是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平台上,而kqueue用在BSD系统中。对于Linux系统,epoll工作模式是首选。
2、worker_connections。connections不是随便设置的,而是与两个指标有重要关联,一是内存,二是操作系统级别的“进程最大可打开文件数”。
内存:每个连接数分别对应一个read_event、一个write_event事件,一个连接数大概占用232字节,2个事件总占用96字节,那么一个连接总共占用328字节,通 过数学公式可以算出100000个连接数大概会占用 31M = 100000 * 328 / 1024 / 1024,当然这只是nginx启动时,connections连接数所占用的nginx。
进程最大可打开文件数:进程最大可打开文件数受限于操作系统,可通过 ulimit -n 命令查询,以前是1024,现在是65535,
3、multi_accept on
告诉nginx收到一个新连接通知后接受尽可能多的连接,默认是 on ,设置为 on 后,多个worker按串行方式来处理连接,也就是一个连接只有一个worker被唤醒,其 他的处于休眠状态,设置为 off 后,多个worker按并行方式来处理连接,也就是一个连接会唤醒所有的worker,直到连接分配完毕,没有取得连接的继续休眠。当你 的服务器连接数不多时,开启这个参数会让负载有一定的降低,但是当服务器的吞吐量很大时,为了效率,可以关闭这个参数。
4、accept_mutex; #设置网路连接序列化,防止惊群现象发生,默认为on
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off,
use epoll; #事件驱动模型select|poll|kqueue|epoll|resig
worker_connections 1024 #最大为65535,默认为1024
}
http块
1、引入支持的媒体文件(MIME)类型。默认的类型是application/octet-stream,具体配置如下:
include mime.types;
default_type application/octet-stream;
2、sendfile on
开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的负载。 注意:如果图片显示不正常把这个改成 off 。
3、tcp_nopush on
必须在 sendfile 开启模式才有效,防止网路阻塞,积极的减少网络报文段的数量(将响应头和正文的开始部分一起发送,而不一个接一个的发送)。
4、keepalive_timeout 60
客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接。用于控制http允许的接收时间。
5、自定义服务日志
log_format 是Nginx的HttpLog模块指令,用于指定Nginx日志的输出日志。当然其中还有更为详细的配置,
格式相关文档地址
access_log定义的是日志的接受目录,总体的配置如下:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
6、gzip on 开启gzip压缩功能。
其他不常用的的参数文档地址:https://zhuanlan.zhihu.com/p/60896914
server块,即虚拟主机的配置
以下只列举我们常用到的配置内容:
1、listen。listen的作用是设置监听的端口,默认是8000,同时也可以配置指定域名下的某个端口。若配置了ssl,端口通常设置为443
指令 listen
作用域 server
默认值 listen*:80 或 *:8000
指令说明 服务监听端口、绑定 IP、监听方式的配置
详细配置信息参考地址
2、server_name somename alias another.alias;
指的是配置的域名地址,支持配置别称。
3、location
作用在于针对不同的路由做不同的代理定向。
可以指向静态页面,也指向后端服务的对应路由。
还支持重定向处理。
4、error_page
异常页面的指定配置,可配置静态页面,也可通过location配置
示例:
server {
listen 80;
server_name 192.168.4.32; #监听地址
location / {
root html; #/html目录
proxy_pass http://127.0.0.1:8080; #请求转向
index index.html index.htm; #设置默认页
}
error_page 500 502 503 504 /50x.html; #出现对应http状态码时,使用50x.html回应客户
location = /50x.thml {
root html; #指定对应目录
}
}
8、负载均衡
NGINX Plus 为 HTTP、TCP 和 UDP 提供多种负载均衡方式。所有这些方式都能够选择分配到每个上游服务器的流量的权重。
-
Round Robin(轮询,默认使用)—— 可按顺序在上游服务器之间分发请求。
-
最少连接——向活跃连接数最少的服务器转发请求。
-
最少时间—— 基于响应时间和活跃连接数进行综合计算,将请求转发到负载最小的服务器 —— 这是只有 NGINX Plus 可以提供的独有功能。
-
Hash(哈希)—— 根据特定的键值分发请求(如客户端 IP 地址或请求 URL)。若上游服务器集群发生变化,NGINX Plus 可以通过应用一致的哈希值来尽量减少负载的重新分配。
-
IP Hash(仅限 HTTP)—— 根据客户端 IP 地址的前三个八位字节进行请求分配。
-
Random with Two Choices—— 随机选择两台服务器并将请求转发到活动连接数较少的服务器(即,上方提到的“最少连接”算法)。通过使用 NGINX Plus,还可以通过“最少时间”算法优化使用效果。
示例:
stream {
upstream stream_backend {
least_conn;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
server backend3.example.com:12345 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
server 192.168.136.132:53;
}
server {
listen 12345;
proxy_pass stream_backend;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
server {
listen 12346;
proxy_pass backend4.example.com:12346;
}
}
Nginx 是如何实现高并发的?
异步,非阻塞,使用了epoll 和大量的底层代码优化。
如果一个server采用一个进程负责一个request的方式,那么进程数就是并发数。正常情况下,会有很多进程一直在等待中。
而nginx采用一个master进程,多个woker进程的模式。
- master进程主要负责收集、分发请求。每当一个请求过来时,master就拉起一个worker进程负责处理这个请求。
- 同时master进程也负责监控woker的状态,保证高可靠性
- woker进程一般设置为跟cpu核心数一致。nginx的woker进程在同一时间可以处理的请求数只受内存限制,可以处理多个请求。
- Nginx 的异步非阻塞工作方式正把当中的等待时间利用起来了。在需要等待的时候,这些进程就空闲出来待命了,因此表现为少数几个进程就解决了大量的并发问题。
每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向上游(后端)服务器转发request,并等待请求返回。那么,这个处理的worker很聪明,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。
此时,如果再有request 进来,他就可以很快再按这种方式处理。而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。
为什么 Nginx 不使用多线程?
Apache: 创建多个进程或线程,而每个进程或线程都会为其分配 cpu 和内存(线程要比进程小的多,所以worker支持比perfork高的并发),并发过大会耗光服务器资源。
Nginx: 采用单线程来异步非阻塞处理请求(管理员可以配置Nginx主进程的工作进程的数量)(epoll),不会为每个请求分配cpu和内存资源,节省了大量资源,同时也减少了大量的CPU的上下文切换。所以才使得Nginx支持更高的并发。