四.Nginx配置
1.位置
/usr/local/nginx/conf/nginx.conf
2.内容
Nginx的主配置文件是nginx.conf,这个配置文件一共由三部分组成,分别为全局块、events块和http块。在http块中,又包含http全局块、多个server块。每个server块中,可以包含server全局块和多个location块。在同一配置块中嵌套的配置块,各个之间不存在次序关系。
配置文件支持大量可配置的指令,绝大多数指令不是特定属于某一个块的。同一个指令放在不同层级的块中,其作用域也不同,一般情况下,高一级块中的指令可以作用于自身所在的块和此块包含的所有低层级块。如果某个指令在两个不同层级的块中同时出现,则采用“就近原则”,即以较低层级块中的配置为准。比如,某指令同时出现在http全局块中和server块中,并且配置不同,则应该以server块中的配置为准。
worker_processes 1; #全局生效
events {
worker_connections 1024; #在events部分中生效
}
http {
include mime.types ; #以下指令在http部分中生效
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server { #以下指令在http的server部分中生效
listen 80;
server_name localhost;
location / { #以下指令在http/server的location中生效
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location - /50x.html {
root html;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
3.Nginx基本结构
... #全局快
events #events块
{
...
}
http #http块
{
... #http全局块
server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN] #location块
{
...
}
}
server #server块
{
...
}
... #http全局块
}
最外层的花括号将内容整体分为两部分,再加上最开始的内容,即第一行省略号表示的nginx.conf一共由三部分组成,分为全局块,events块和http块。在http块中,又包含http全局块,多个server块。每个server块中,可以包含server全局块和多个location块。在同一块配置中嵌套的配置块,各个之间不存在次序关系。
配置文件支持大量可配置的指令,绝大多数指令不是特定属于某一个块的。同一个指令放在不同层级的块中,其作用域也不同,一般情况下,高一级块中的指令可以作用于自身所在的块和此块包含的所有低层级块。如果某个指令在两个不同层级的块中同时出现,则采用“就近原则”,即以较低层级块中的配置为准。比如,某指令同时出现在http全局块中和server块中,并且配置不同,则应该以server块中的配置为准。
4.三部分
第一部分:全局块
从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配 置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以 及配置文件的引入等。
配置运行 Nginx 服务器用户(组)
# 配置可以运行nginx服务器的用户和用户组
user user [group];
# 如果希望所有用户都可以启动Nginx,则配置为 user nobady;
user root root;
配置 worker processes 相关
#【可配置调优项】
# 配置允许生成的worker processes(工作进程)数
# 理论上来说 worker processes 值越大,可以支持的并发数量也越多,性能就越好
# 但实际上它的数量,还要受到服务器 CPU 处理器数量以及软件配置制约
# 从Nginx1.9.10开始可以使用auto值,系统自动检测 CPU 处理器数量,设置想要的工作进程数量
# 当然你设置的工作进程数量超过 CPU 处理器数量也行,但是这样就出现 CPU 的进程切换,影响性能
worker processes auto; # 可以用lscpu命令来找出CPU的核数
#【可配置调优项】
#设定nginx的worker进程工作在哪几个CPU核心上,上面的worker进程数量最好和这里的数量对应
#CPU几核心就用几位数,1表示使用,0表示不使用,从Nginx1.9.10可以使用auto值,系统自动设置
#这样绑定只是说明每个CPU只运行一个Nginx进程,并不能保证其他进程下次运行时,不会跑到当前这些CPU核心上去
#虽然限制了worker进程的范围,但是没有限制其他进程,如果想限制这些CPU核心不能被其他进程使用
#就只能做CPU隔离,在操作系统启动的时候就隔离出去。但这样对于内核级别的进程,比如中断还是可能会跑过去,所以
#真正做到严格隔离也可以,就是比较麻烦。
worker_cpu_affinity auto;
例如:
#2 CPU(2 Core) + 2 worker_processes(每个worker_processes 使用1个CPU)
#worker_processes 2;
#worker_cpu_affinity 01 10;
#2 CPU(2 Core) + 8 worker_processes(每个worker_processes 使用1个CPU)
#worker_processes 8;
#worker_cpu_affinity 01 10 01 10 01 10 01 10; (CPU与工作进程数量不对应时,多个工作进程抢占,轮流使用同一个CPU)
#4 CPU(4 Core) + 4 worker_processes(每个worker_processes 使用1个CPU)
#worker_processes 4;
#worker_cpu_affinity 0001 0010 0100 1000;
#8 CPU(8 Core) +2 worker_processes(每个worker_processes 使用1个CPU)
#worker_processes 2;
#worker_cpu_affinity 10101010 01010101;
#8 CPU(8 Core) + 8 worker_processes(每个worker_processes 使用1个CPU)
#worker_processes 8;
#worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
#【可配置调优项】
#这个指令是指当一个 nginx 进程打开的最多文件描述符数目;用于指定单个worker进程可以打开最大文件描述符数量,
#每个连接都会打开一个文件,所以对于并发非常大的场景这个值应该设置的大一点
#理论值应该是最多打开文件数(ulimit -n)与 nginx 进程数相除,但是 nginx 分配请求并不是那么均匀,所以最好
#与 ulimit -n 的值保持一致。现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。
#这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,
#这时会返回502错误
#这个配置,在默认的配置文件中没有,受限于Linux系统设置,默认是1024个;可以自行修改,比如改成 65535 个。
#把这个值设高,这样nginx就不会有“too many open files”问题了
#如果Nginx作为web服务器,worker_rlimit_nofile要大于等于worker_connections,因为Nginx自己也要打开一些文件。
#如果Nginx作为代理服务器,worker_rlimit_nofile要是worker_connections的2倍,原因是Nginx作为代理的时候,面向请求是一个套接字,
#面向后端应用服务器也是一个套接字,所以一个请求在Nginx上要使用2个套接字,所以worker_rlimit_nofile要是worker_connections的2倍
worker_rlimit_nofile 65535;
#【可配置调优项】
#worker进程的优先级,与使用 nice 命令完成类似:负数意味着更高的优先级。允许范围通常在 -20 到 20 之间。
worker_priority -10;
配置 ssl 相关
#定义SSL硬件加速器,如果支持HTTPS的话,每一个都创建SSL会话,加密、解密、会话建立和断开等这些对CPU的占用率非常高,
#一个服务器可以承载的HTTPS会话大概是HTTP会话的1/5左右。服务器可以安装硬件的SSL会话加速器,那么你这里就可以指定,
#这样SSL会话就不会占用CPU资源。这个就跟高端服务器网卡带特殊芯片一样都是为了减轻CPU负担。
ssl_engine device;
配置错误日志存放路径及级别
#错误日志路径,这个error_log变量可以设置在任何地方
#可以在全局块中配置、在http全局块中配置、在server全局块中配置、在location块中配置、在stream块以及mail块中配置
#该配置有两个参数,第一个值设置为日志存放的实际路径,第二个值为日志级别
#debug级别必须在编译安装时要--with-debug启用debug功能
#它有debug、info、notice、warn、error、crit、alert、emerg,默认级别是error。
#如果设置为error级别,日志中会包括error级别和以上级别的信息,即error、crit、alert、emerg级别的信息。
error_log /var/log/nginx/error.log error;
配置PID文件存放路径及名称
#配置nginx服务器运行时的pid文件存放路径和名称
pid logs/nginx.pid;
配置锁文件
#锁文件,这个和events中的accept_mutex有关,如果这个参数是off,那么就不会出现锁文件。
lock_file /var/lock/nginx.lock
第二部分:events块
events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否 允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
上述例子就表示每个 work process 支持的最大连接数为 1024.
这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
配置事件驱动模型
# 一般不用设置,因为Nginx会自动选择当前系统中所支持的最有效率的IO模型。#select、poll是标准方法大多系统都支持。
#kqueue:是FreeBSE 4.1+ OpenBSD 2.9+和Mac OS X上用的
#epool:在Linux 2.6+开始支持# 还有其它很多事件驱动模型,就不列举了,最常用的高效率模型是 epoll
# use [epoll|rtsig|select|poll|kqueue|/dev/poll]
use epool;
配置网络连接相关
#如果启用了 accept_mutex,则工作进程将轮流接受新连接。否则,将新连接通知给所有工作进程,如果新连接数量较少,
#某些工作进程可能会浪费系统资源。即造成 “惊群” 问题。
#“惊群” 大意是指在 Nginx 多进程环境下,当某一时刻只有一个网络连接到来时,因为新连接会通知所有工作进程,
#那么会导致所有所有睡眠进程都会被同时叫醒,但是只有一个进程可以获得连接。如果每次唤醒的进程数目太多,会影响一些性能。
#为了解决这样的问题,可以设置 accept_mutex 为开启状态,这样多个 Nginx 进程接收网络连接时将会进行序列化接收,防止多个进程对连接的争抢
accept_mutex on; # 默认 accept_mutex off;
#如果启用了 accept_mutex,则指定另外工作进程请求新链接失败后,间隔多少毫秒可以发起第二次请求。默认500ms,不过如果accept_mutex是
#off,那就没有必要设置这个参数了。
accept_mutex_delay time; # 时间单位是毫秒,默认为 accept_mutex_delay 500ms;
#如果 multi_accept 被禁用,工作进程将一次只接收一个新连接。否则,工作进程将一次接受所有新连接。
multi_accept off; # multi_accept on;
#设置工作进程可以打开的同时连接的最大数量
#应该注意的是,这个数字包括了所有连接(例如与代理服务器的连接等),而不仅仅是客户端的连接。另一个要考虑因素是实际的并发连接数不能超过最
#大打开文件数的限制,可以通过 worker_rlimit_nofile 来修改
worker_connections 1024;
第三部分:http块
http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这个模块中。
前面已经提到,http块中可以包含自己的全局块,也可以包含server块,server块中又可以进一步包含location块,在本书中我们使用“http全局块”来表示http中自己的全局块,即http块中不包含在server块中的部分。
可以在http全局块中配置的指令包括文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。
需要注意的是:http 块也可以包括 http全局块、server 块。
http全局块
引入文件
在浏览器中可以显示的内容有HTML、XML、PNG、GIF及Flash等种类繁多的文本、媒体等资源,浏览器为区分这些资源,需要使用MIME Type。换言之,MIME Type是网络资源的媒体类型。Nginx服务器作为Web服务器,必须能够识别前端请求的资源类型。
#包含其他的配置文件,可以放在配置文件的任何地方,但是要注意你包含进来的配置文件一定符合配置规范
#比如说你include进来的配置是worker_processes指令的配置,而你将这个指令包含到了http块中
#这肯定是不行的
include mime.types; # #文件扩展名与文件类型映射表
default_type application/octet-stream; #设置输出文件类型,默认为text/plain
设置Nginx访问日志格式及存放路径
Nginx日志对于统计、系统服务排错很有用。Nginx日志主要分为两种:access_log(访问日志)和error_log(错误日志)。通过访问日志我们可以得到用户的IP地址、浏览器的信息,请求的处理时间等信息。
可以应用access_log指令的作用域分别有http,server,location,limit_except。也就是说,在这几个作用域外使用该指令,Nginx会报错。
#以下为主要变量说明:
# $bytes_sent 发送给客户端的总字节数
# $body_bytes_sent 发送给客户端的字节数,不包括响应头的大小
# $connection 连接序列号
# $connection_requests 当前通过连接发出的请求数量
# $msec 日志写入时间,单位为秒,精度是毫秒
# $pipe 如果请求是通过http流水线发送,则其值为"p",否则为“."
# $request_length 请求长度(包括请求行,请求头和请求体)
# $request_time 请求处理时长,单位为秒,精度为毫秒,从接受用户请求的第一个字节到发送完响应数据的实际,
# 包括接受请求数据的实际、程序响应时间、输出数据时间
# $status 服务器响应状态码
# $time_iso8601 标准格式的本地时间,形如“2017-05-24T18:31:27+08:00”
# $time_local 通用日志格式下的本地时间,如"24/May/2017:18:31:27 +0800"
# $host:客户端请求的Host头域值
# $http_referer 表示从哪个链接跳转过来
# $http_user_agent 客户端浏览器信息。
# $remote_addr 客户端IP
# $http_x_forwarded_for 当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是
# 代理服务器也要进行相关的x_forwarded_for设置。
# $request 完整的原始请求行,如 "GET / HTTP/1.1"
# $remote_user 客户端用户名称,针对启用了用户认证的请求
# $request_uri:表示完整的请求地址,如 "https://daojia.com/"
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 path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
# path 指定日志的存放位置。
# format 指定日志的格式。默认使用预定义的combined。
# buffer 用来指定日志写入时的缓存大小。默认是64k,含义是日志先同步到缓存中,这样提升性能,避免每产生
# 一条日志都立即写入磁盘文件。
# gzip 日志写入前先进行压缩。压缩率可以指定,从1到9数值越大压缩比越高,同时压缩的速度也越慢。默认是1。
# flush 设置缓存的有效时间。如果超过flush指定的时间,缓存中的内容将被清空。
# if 条件判断。如果指定的条件计算为0或空字符串,那么该请求不会写入日志。
# access_log log/access.log main;
# Nginx预定义了名为combined日志格式,如果不想使用可以如上使用自定义规则 main
access_log /var/logs/nginx-access.log buffer=32k gzip flush=1m
# 关闭访问日志
access_log off;
设置连接方向
# 配置连接超时时间,保持连接的时长默认为75秒,指定客户端连接保持活动的超时时间,超过这个时间服务器就
# 自动断开连接,此指令可以在http块、server块或location块中配置。
# !!!但是有些浏览器最多只保持 60 秒,所以统一设置为 60
# 与用户建立会话连接后,Nginx服务器可以保持这些连接打开一段时间
# timeout,服务器端对连接的保持时间
# header_timeout,可选项,在应答报文头部的
# Keep-Alive域设置超时时间:“Keep-Alive:timeout= header_timeout”。
# 报文中的这个指令可以被Mozilla或者Konqueror识别。
keepalive_timeout timeout [header_timeout]
# 下面配置的含义是,在服务器端保持连接的时间设置为60 s,发给用户端的应答报文头部中Keep-Alive域的
#超时时间设置为50 s。
keepalive_timeout 60 50
# 一次长连接允许发起的最大请求数量,用户与服务器建立连接后,通过此连接可以发起的最多多少次请求,
# 此指令可以在http块、server块或location块中配置。
# Nginx服务器端和用户端建立会话连接后,用户端通过此连接发送请求。指令keepalive_requests用于限制
# 用户通过某一连接向Nginx服务器发送请求的次数。默认是100
keepalive_requests number;
#对某些老版本的浏览器不使用长连接,none表示对老版本浏览器不做禁用 msie6 表示对微软的IE6禁用长连接
#该参数可以定义在http{}段中,也可以定义在server{}段中、location{}段中
keepalive_disable [msie6|safari|none]
设置 TCP 相关
#指定是否使用sendfile系统调用来传输文件。
#sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和
#用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。
#sendfile 是一个系统调用,直接在内核空间完成文件发送,不需要先 read 再 write,没有上下文切换开销。
#默认为off,可以在http块,server块,location块。
sendfile on;
#设置sendfile最大数据量,此指令可以在http块、server块或location块中配置
#其中,size值如果大于0,Nginx进程的每个worker process每次调用sendfile()传输的数据量最大不能超过
#这个值(这里是128k,所以每次不能超过128k);如果设置为0,则无限制。默认值为0。
# sendfile_max_chunk size;
sendfile_max_chunk 128K;
#tcp_nopush 是 FreeBSD 的一个 socket 选项,对应 Linux 的 TCP_CORK,Nginx 里统一用 tcp_nopush
#来控制它,并且只有在启用了 sendfile 之后才生效。启用它之后,数据包会累计到一定大小之后才会发送,
#减小了额外开销,提高网络效率。
#只有在sendfile启用时,改参数启用才生效
#该参数可以定义在http{}段中,也可以定义在server{}段中、location{}段中
tcp_nopush on;
#TCP_NODELAY 也是一个 socket 选项,启用后会禁用 Nagle 算法,尽快发送数据,某些情况下可以节约
#200ms(Nagle 算法原理是:在发出去的数据还未被确认之前,新生成的小数据先存起来,凑满一个 MSS 或者
#等到收到确认后再发送)。Nginx 只会针对处于 keep-alive 状态的 TCP 连接才会启用 tcp_nodelay。
tcp_nodelay on;
#可以看到 TCP_NOPUSH 是要等数据包累积到一定大小才发送,TCP_NODELAY 是要尽快发送,二者相互矛盾。实际上,它们确实可以一起用,最终的效果是先填满包,再尽快发送。
设置 gzip 相关
Nginx是一个高性能的HTTP和反向代理服务器,默认提供了gzip的压缩模块:ngx_http_gzip_module。
模块的最开头便介绍道:能帮助我们减少一半甚至更多的传输数据大小。
#我们在上线前,代码(JS、CSS 和 HTML)会做压缩,图片也会做压缩。对于文本文件,在服务端发送响应之前进行
#GZip 压缩也很重要,通常压缩后的文本大小会减小到原来的 1/4 - 1/3。
#是否开启gzip功能,也就是在服务器响应客户端是是否把响应数据进行压缩,默认为off
#这个参数可以设置在在http{}段中、server{}段中、location {}段中
gzip on;
#用于设置在使用压缩功能时,是否发送带有Vary:Accept-Econding头的响应信息。该参数主要是告诉数据
#接收方,数据经过了压缩
#开启效果是客户端接收的响应头部中增加了 Accept-Ecoding:gzip的信息。
gzip_vary on;
#压缩等级.1压缩比最小,处理速度快.9压缩比最大,比较消耗cpu资源,处理速度最慢,
#但是因为压缩比最大,所以包最小,传输速度快
gzip_comp_level 6;
#gzip实现压缩的时候使用缓冲的大小,第一个参数是缓存空间个数,第二个是缓存大小。
#认情况下size大小为一个内存页,4K或者8K,取决于系统一个内存页的大小。
#这个参数可以设置在在http{}段中、server{}段中、location {}段中
gzip_buffers 16 8k;
#内容长度大于多少字节时才压缩,页面字节数从header偷得content-length中获取。
#默认是20,不管页面多大都进行压缩.建议设置成大于1k的字节数,小于1k可能会越压越大。
#因为对于数据量大压缩才明显,小数据压缩不明显而且还消耗资源。也就是当响应页面大于该值时才启用压缩。
#响应页面大小可以通过HTTP响应头中的Content-Length指令获取。不过由于ngx_http_gzip_module
#通常使用Chunked动态编码压缩,所以Conten-Length或不存在或者被忽略,该指令不起作用。
#这个参数可以设置在在http{}段中、server{}段中、location {}段中
gzip_min_length 1k;
#默认情况下,nginx不会对被代理的请求进行压缩,它通过Via头识别请求是不是被代理过。如果要对被代理的请求
#进行压缩,可以配置这个参数
#off 不压缩所有被代理的请求
#expired 如果返回头包含Expires,则开启压缩
#no-cached 如果返回头包含Cache-Control,值为no-cache,则开启压缩
#no-store 如果返回头包含Cache-Control,值为no-store,则开启压缩
#private 如果返回头包含Cache-Control,值为private,则开启压缩
#no_last_modified 如果返回头没有包含Last-Modified,则开启压缩
#no_etag 如果返回头没有包含ETag,则开启压缩
#auth 如果请求头包含Authorization,则开启压缩
#any 压缩所有被代理请求
gzip_proxied no-cache no-store private expired auth;
#gzip_disable 指令接受一个正则表达式,当请求头中的 UserAgent 字段满足这个正则时,
#响应不会启用 GZip,这是为了解决在某些浏览器启用 GZip 带来的问题。特别地,指令值 msie6
#等价于 MSIE [4-6]\.,但性能更好一些。另外,Nginx 0.8.11 后,msie6 并不会匹配 UA 包含 SV1
#的 IE6(例如 Windows XP SP2 上的 IE6),因为这个版本的 IE6 已经修复了关于 GZip 的若干 Bug。
gzip_disable "msie6";
#默认 Nginx 只会针对 HTTP/1.1 及以上的请求才会启用 GZip,因为部分早期的 HTTP/1.0 客户端在处理 GZip
#时有 Bug。现在基本上可以忽略这种情况,于是可以指定 gzip_http_version 1.0 来针对 HTTP/1.0 及以上的请
#求开启 GZip。
gzip_http_version 1.0;
#压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn.
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
#当开启时,如果客户端浏览器不支持压缩,那么Nginx将返回解压后的数据;如果支持压缩将忽略此选项。
gunzip_static on;
设置客户端相关
#客户端请求首部超时时间,定义服务器读取客户端请求首部的最长时间,如果在段时间内
#客户端无法完成发送完整的客户端请求首部信息,则返回给客户端408超时错误信息。默认60秒。
#该参数可以定义在http{}段中,也可以定义在server{}段中。
client_header_timeout 60s;
#读取HTTP请求的包体的超时时长,道理和上面一样。默认也是60秒
#该参数可以定义在http{}段中,也可以定义在server{}段中。
client_body_timeout 60s;
#设置读取客户端请求头的缓冲区大小,通常来说1K就够用,但是如果客户端请求中包含一个比较大的cookies或者是来自WAP客户端,
#那么1K就不够了,这是可能收到Nginx 400的错误,而且不是每次都收到,所以排查困难。一般这个大小都是系统分页的倍数。可用
#getconf PAGESIZE来获取。
client_header_buffer_size 4k;
#设置允许的客户端最大请求包体大小,客户端发一个特别大的请求,服务器拒绝。默认1M。
#这个参数可以设置在http{}段中、server{}段中以及location {}段中。
#在允许用户上传时的场景下,设置这个很有用。用户上传时它的body首部中的Content-length就会
#有上传的这个包的大小。
client_max_body_size 1m;
#发送响应超时时长,服务器端要发送响应数据给客户端,客户端不接收或者因某种原因客户端没有收到,那么服务端最多等多久
#这个不是说整个响应的传输时长。这个超时时间生效条件是在客户端和服务器成功建立连接之后,
#这个参数可以设置在在http{}段中、server{}段中以及location {}段中
send_timeout 60s;
#限制客户端每秒上传的字节数量,就是为了避免把服务器带宽都占用了。默认0,无限制。
#这个参数可以设置在在http{}段中、server{}段中、location {}段中以及if in location中
limit_rate 0;
#nginx向客户端发送响应报文时,如果超出了设定的时长,那么就开始限速,这里限制的是
#客户端的下载速率,这个速率是从limit_rate中获取的。所以这里不需要指定,只需要指定
#超时时间就可以,默认是0,也就是没有时长限制。
#这个参数可以设置在在http{}段中、server{}段中、location {}段中以及if in location中
limit_rate_after 0;
设置fastcgi相关
#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
#指定连接到后端FastCGI 的超时时间。
fastcgi_connect_timeout 300;
#读取 是指nginx进程向fastcgi进程发送request的整个过程的超时时间
fastcgi_send_timeout 300;
#发请求 是指fastcgi进程向nginx进程发送response的整个过程的超时时间
fastcgi_read_timeout 300;
#指定读取FastCGI 应答第一部分需要用多大的缓冲区
fastcgi_buffer_size 64k;
#指定本地需要用多少和多大的缓冲区来缓冲 FastCGI 的应答。
fastcgi_buffers 4 64k;
#默认值是 fastcgi_buffers 的两倍。
fastcgi_busy_buffers_size 128k;
#在写入 fastcgi_temp_path 时将用多大的数据块,默认值是 fastcgi_buffers 的两倍。
fastcgi_temp_file_write_size 128k;
其它
#开启压缩功能的一些问题:很多WEB服务器都支持压缩比如IIS、Tomcat、Apache等。如果前端Nginx
#也开启了压缩,就相当于数据经过了2层压缩,比如如果Nginx和Tomcat都开启对JavaScript脚本进行
#压缩的话,在很多浏览器都会出现脚本运行异常的情况,只有在chrome浏览器正常。表现的现象是首次
#运行正常,再次刷新就304.你把其中一台服务器的压缩功能关闭就可以了。
#是否打开文件缓存功能,它缓存的是文件描述符、大小、修改时间、目录结构以及查找文件时的错误,
#比如文件没有找到,如果要开启的话 open_file_cache max=N [inactive=time],设置一个最大
#缓存条目,如果满了则根据LNU算法进行置换,以及每个缓存元素的活动时长,默认60秒,也就是说在指定
#时间内没有被访问过,就会被从缓存中移除。
#这个参数可以设置在在http{}段中、server{}段中、location {}段中
open_file_cache off;
#设置是否缓存在文件查找是出现的文件查找错误信息。这些错误信息是因为启用了open_file_cache功能才会有的
#默认是OFF则表示不缓存错误信息,这个参数可以设置在在http{}段中、server{}段中、location {}段中
#该参数要在open_file_cache on时才有意义
open_file_cache_errors off;
#设置多久检测一次缓存内容的是否有效,默认60秒,该参数要在open_file_cache on时才有意义
#这个参数可以设置在在http{}段中、server{}段中、location {}段中
open_file_cache_valid 60s;
#在非活动时长内,一个缓存条目被访问的次数超过这里定义的次数,那么这个条目即便超过了非活动时长
#也不会被删除。这个非活动时长就是open_file_cache max=N inactive=60s;中定义的。
open_file_cache_min_use 1;
#控制如果客户端请求首部是一个无效信息,服务器是否忽略。默认是on,就是忽略。
ignore_invalid_headers on;
#当用户访问一个文件,如果该文件不存在,是否把这个信息记录到错误日志中。默认是开启。on。
#这个参数可以设置在在http{}段中、server{}段中、location {}段中
log_not_found on;
#是否在错误页面中显示Nginx版本号,默认是显示的,也就是ON #这个参数可以设置在在http{}段中、server{}段中、location {}段中
server_tokens off;
server 块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。这里的“主机”或“空间”是由实体的服务器延伸而来,硬件系统可以基于服务器群,或者单个服务器等。虚拟主机技术主要应用于HTTP、FTP及EMAIL等多项服务,将一台服务器的某项或者全部服务内容逻辑划分为多个服务单位,对外表现为多个服务器,从而充分利用服务器硬件资源。从用户角度来看,一台虚拟主机和一台独立的硬件主机是完全一样的。
在使用Nginx服务器提供Web服务时,利用虚拟主机的技术就可以避免为每一个要运行的网站提供单独的Nginx服务器,也无需为每个网站对应运行一组Nginx进程。虚拟主机技术使得Nginx服务器可以在同一台服务器上只运行一组Nginx进程,就可以运行多个网站。
在前面提到过,每一个http块都可以包含多个server块,而每个server块就相当于一台虚拟主机,它内部可有多台主机联合提供服务,一起对外提供在逻辑上关系密切的一组服务(或网站)。
和http块相同,server块也可以包含自己的全局块,同时可以包含多个location块。在server全局块中,最常见的两个配置项是本虚拟主机的监听配置和本虚拟主机的名称或IP配置。
http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
配置网络监听
# 配置网络监听,主要有三种方式
# 第一种配置监听 IP 地址
listen address[:port] [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
# 第二种配置监听端口
listen port [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
第三种配置 UNIX Domain Socket
listen unix:path [default_server] [ssl] [http2 | spdy] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
Default:
#address:IP地址,如果是 IPv6 的地址,需要使用中括号“[]”括起来,比如[fe80::1]等。
#port:端口号,如果只定义了 IP 地址,没有定义端口号,默认使用 80 端口号。
#path:socket 文件路径,如 /var/run/nginx.sock 等。
#default_server:将所在的server块作为整个web服务的默认server块。
#如果没有设置这个参数,那么将会以在nginx.conf中找到的第一个server块作为默认server块。
#需要默认虚拟主机的原因是,当一个请求无法匹配配置文件中的所有主机域名时,就需要使用默认虚拟主机。
#setfib=number:Nginx-0.8.44 中使用这个变量为监听socket关联路由表,目前只对 FreeBSD 起作用,不常用
#backlog=number:表示TCP中backlog队列的大小。在 FreeBSD 中默认为-1,其它平台默认为 511,表示不予设置,在TCP建立三次握手的过程中,
#进程还没有开始处理监听句柄,这时backlog队列将会防止这些新连接,可如果backlog队列已满,
#还有新的客户端试图通过三次握手建立TCP连接,这时客户端将建立失败。
#revbuf=size:设置监听 socket 接收缓存区大小。
#sndbuf=size:设置监听 socket 发送缓存区大小。
#deferred:将 accept() 设置为 Deferred 模式。在设置该参数后,若用户发起建立连接请求,并且完成了TCP的三次握手,内核也不会为了
#这次的连接调度worker进程来处理,只有用户真的发送请求数据时,(内核已经在网卡中受到请求数据包),
#内核才会唤醒worker进程处理这个连接,这个参数适用于大并发的情况下,它减轻了worker进程的负担,
#当请求数据来临时,worker进程才会开始处理这个连接。
#accept_filter:设置accept过滤器,只对FreeBSD操作系统有用。
#bind:绑定当前端口/地址对。如127.0.0.1:8000。一般情况下,对于端口相同而 IP 地址不同的多个连接,
#Nginx 服务器将只使用一个监听命令,并使用 bind() 处理端口相同的所有连接。
#ssl:在当前监听的端口上建立的连接必须基于ssl协议,此标识符和Nginx服务器提供的 HTTPS 服务有关。
#默认设置监听,即监听所有地址的 80 端口和8000端口
listen *:80 | *:8000;
举例:
#监听具体的 IP 和 具体的端口号上的连接
listen 192.168.1.10:8000;
#监听具体 IP 上的所有连接
listen 192.168.1.10;
#监听具体端口号上的所有 IP 连接, 等同于 listen *:8000;
listen 8000;
主机名称配置
server_name name […]; # 默认server_name “”;
server_name 后可以跟多个主机名称,如server_name www.web.com web.com test.web.com;
server_name 与host的匹配优先级如下:
1、首先选择所有字符串完全匹配的server_name,如www.web.com.
2、其次选择通配符在前面的server_name,如*.web.com。
3、在其次选择通配符在后面的server_name,如www.web.*。
4、最后选择使用正则表达式才匹配的server_name,如~^.web.com$。
#支持使用通配符和正则表达式。比如 *.a.com www.a.*
#但是通配符只能用在三或者两段字符串组成的域名的首部或者尾部。
其它
# 设置字符集
charset utf-8;
# 设置访问首页
#配置块:http、server、location
#index file …;#默认:index index.html;
#访问站点的URI时/,这时一般时返回网站的首页,而这与root和alias都不同,
#这里用nginx_http_index_module模块提供的index配置实现,index后可以跟多个文件参数,
#ngiunx将会按照顺序来访问这些文件
index index.php;
#定义资源文件相对于HTTP请求的根目录
#可以用在http段、server段、location段,如果用在http段,则对所有的server段生效,
#如果用在server段,则对server段下的所有的location生效。
root /home/wwwroot/hewaApi/public;
location块
location 指令是 nginx 中最关键的指令之一,location 指令的功能是用来匹配不同的 URI 请求,进而对请求做不同的处理和响应,这其中较难理解的是多个 location 的匹配顺序,本文会作为重点来解释和说明。对虚拟主机名称 (也可以是IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。 地址定向、数据缓 存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
开始之前先明确一些约定,我们输入的网址叫做请求 URI,nginx 用请求 URI 与 location 中配置的 URI 做匹配。
配置location块
location 语法
Location 块通过指定模式来与客户端请求的URI相匹配。
Location基本语法:
- 匹配 URI 类型,有四种参数可选,当然也可以不带参数。
- 命名location,用@来标识,类似于定义goto语句块。
location [ = | ~ | ~* | ^~ ] /URI { … }
location @/name/ { … }
location匹配命令解释
location匹配顺序
nginx有两层指令来匹配请求 URI 。第一个层次是 server 指令,它通过域名、ip 和端口来做第一层级匹配,当找到匹配的 server 后就进入此 server 的 location 匹配。
location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求URI 会按如下规则进行匹配:
先精准匹配 = ,精准匹配成功则会立即停止其他类型匹配;
没有精准匹配成功时,进行前缀匹配。先查找带有 ^~ 的前缀匹配,带有 ^~ 的前缀匹配成功则立即停止其他类型匹配,普通前缀匹配(不带参数 ^~ )成功则会暂存,继续查找正则匹配;
= 和 ^~ 均未匹配成功前提下,查找正则匹配 ~ 和 ~* 。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配;
所有正则匹配均未成功时,返回步骤 2 中暂存的普通前缀匹配(不带参数 ^~ )结果
以上规则简单总结就是优先级从高到低依次为(序号越小优先级越高):
1. location = # 精准匹配
2. location ^~ # 带参前缀匹配
3. location ~ # 正则匹配(区分大小写)
4. location ~* # 正则匹配(不区分大小写)
5. location /a # 普通前缀匹配,优先级低于带参数前缀匹配。
6. location / # 任何没有匹配成功的,都会匹配这里处理
其他location配置相关
匹配问号后的参数
请求 URI 中问号后面的参数是不能在 location 中匹配到的,这些参数存储在 $query_string 变量中,可以用 if 来判断。
例如,对于参数中带有单引号 ’ 进行匹配然后重定向到错误页面。
/plus/list.php?tid=19&mid=1124‘
if ( $query_string ~* “.*[;’<>].*” ){
return 404;
}
location URI结尾带不带 /
关于 URI 尾部的 / 有三点也需要说明一下。第一点与 location 配置有关,其他两点无关。
- location 中的字符有没有 / 都没有影响。也就是说 /user/ 和 /user 是一样的。
- 如果 URI 结构是 https://domain.com/ 的形式,尾部有没有 / 都不会造成重定向。因为浏览器在发起请求的时候,默认加上了 / 。虽然很多浏览器在地址栏里也不会显示 / 。这一点,可以访问baidu验证一下。
- 如果 URI 的结构是 https://domain.com/some-dir/ 。尾部如果缺少 / 将导致重定向。因为根据约定,URL 尾部的 / 表示目录,没有 / 表示文件。所以访问 /some-dir/ 时,服务器会自动去该目录下找对应的默认文件。如果访问 /some-dir 的话,服务器会先去找 some-dir 文件,找不到的话会将 some-dir 当成目录,重定向到 /some-dir/ ,去该目录下找默认文件。可以去测试一下你的网站是不是这样的。
命名 location
带有 @ 的 location 是用来定义一个命名的 location,这种 location 不参与请求匹配,一般用在内部定向。用法如下:
location / {
try_files $uri $uri/ @custom
}
location @custom {
# ...do something
}
上例中,当尝试访问 URI 找不到对应的文件就重定向到我们自定义的命名 location(此处为 custom)。
值得注意的是,命名 location 中不能再嵌套其它的命名 location。
location 实际使用建议
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
这里是直接转发给后端应用服务器了,也可以是一个静态首页。第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}
第二个必选规则是处理静态文件请求,这是 nginx 作为 http 服务器的强项,有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用:
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三个规则就是通用规则,用来转发动态请求到后端应用服务器,非静态文件请求就默认是动态请求,自己根据实际把握,毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了:
location / {
proxy_pass http://tomcat:8080/
}
rewrite 配置详解
前言
nginx 通过 ngx_http_rewrite_module 模块支持 URI 重写、支持 if 条件判断,但不支持 else。
rewrite 只能放在 server { } 、 location { } 、 if { } 中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如http://aaa.com/a/we/index.php?id=1&u=str只对/a/we/index.php重写。语法为 rewrite regex replacement [flag];
指令执行顺序
表面看 rewrite 和 location 功能有点像,都能实现跳转,主要区别在于 rewrite 是在同一域名内更改获取资源的路径,而 location 是对一类路径做控制访问或反向代理,可以 proxy_pass 到其他机器。很多情况下 rewrite 也会写在 location 里,它们的执行顺序是:
执行 server 块的 rewrite 指令(这里的块指的是 server 关键字后{}包围的区域,其它 xx 块类似)
执行location匹配
执行选定的location中的rewrite指令
如果其中某步 URI 被重写,则重新循环执行1-3,直到找到真实存在的文件;
如果循环超过 10 次,则返回 500 Internal Server Error 错误。
指令详解
if 指令
语法:if(condition) {…}
作用域:server、location
功能:该指令用来支持条件判断,并根据条件判断结果选择不同的 Nginx 配置。
if 中的几种判断条件
- 一个变量名;false 如果这个变量是空字符串或者以0开始的字符串;
- 使用 = ,!= 比较的一个变量和字符串
- 是用 ~, ~* 与正则表达式匹配的变量,如果这个正则表达式中包含},;则整个表达式需要用” 或’ 包围
- 使用 -f ,!-f 检查一个文件是否存在
- 使用 -d, !-d 检查一个目录是否存在
- 使用 -e ,!-e检查一个文件、目录、符号链接是否存在
- 使用 -x ,!-x 检查一个文件是否可执行
示例:
set $variable "0";
if ($variable) {
# 不会执行,因为 "0" 为 false
break;
}
# 使用变量与正则表达式匹配 没有问题
if ( $http_host ~ "^star\.igrow\.cn$" ) {
break;
}
# 字符串与正则表达式匹配 报错
if ( "star" ~ "^star\.igrow\.cn$" ) {
break;
}
# 检查文件类的 字符串与变量均可
if ( !-f "/data.log" ) {
break;
}
if ( !-f $filename ) {
break;
}
return 指令
语法:
return code [text];
return code URL;
return URL;
作用域:server,location,if
功能:停止处理并将指定的 code 码返回给客户端。 非标准 code 码 444 关闭连接而不发送响应报头。
该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。If 指令不支持嵌套,不支持多个条件 && 和 || 处理。
从0.8.42版本开始, return 语句可以指定重定向 URI (状态码可以为如下几种 301,302,303,307),
也可以为其他状态码指定响应的文本内容,并且重定向的 URI 和响应的文本可以包含变量。
有一种特殊情况,就是重定向的url可以指定为此服务器本地的 URI,这样的话,nginx 会依据请求的协议 $scheme, server_name_in_redirect 和 port_in_redirect 自动生成完整的 URI。
示例:如果访问的 URI 以 .sh 或 .bash 结尾,则返回 403 状态码
location ~ .*\.(sh|bash)?$
{
return 403;
}
rewrite 指令
语法:rewrite regex replacement [flag];
作用域:server 、location、if
功能:如果一个URI匹配指定的正则表达式regex,URI就按照 replacement 重写。
rewrite 按配置文件中出现的顺序执行。可以使用 flag 标志来终止指令的进一步处理。
如果 replacement 以 http:// 、 https:// 或 $ scheme 开始,将不再继续处理,这个重定向将返回给客户端。
示例:第一种情况,重写的字符串带 http://
location ^~ /redirect {
# 当匹配前缀表达式 /redirect/(.*)时 请求将被临时重定向到 http://www.$1.com
# 相当于 flag 写为 redirect
rewrite ^/(.*)$ http://www.$1.com;
return 200 "ok";
}
在浏览器中输入 127.0.0.1:8080/redirect/baidu ,则临时重定向到 www.baidu.com 后面的 return 指令将没有机会执行了。
location ^~ /redirect {
rewrite ^/(.*)$ www.$1.com;
return 200 "ok";
}
# 发送请求如下
# curl 127.0.0.1:8080/redirect/baidu
# ok
此处没有带 http:// 所以只是简单的重写。请求的 URI 由 /test1/baidu 重写为 www.baidu.com 因为会顺序执行 rewrite 指令,所以 下一步执行 return 指令,响应后返回 ok
flag 有四种参数可以选择:
last 停止处理后续 rewrite 指令集,然后对当前重写的新 URI 在 rewrite 指令集上重新查找。
break 停止处理后续 rewrite 指令集,并不再重新查找,但是当前location 内剩余非 rewrite 语句和 location 外的 非rewrite 语句可以执行。
redirect 如果 replacement 不是以 http:// 或 https:// 开始,返回 302 临时重定向
permanent 返回 301 永久重定向
示例 1:
# rewrite 后面没有任何 flag 时就顺序执行
# 当 location 中没有 rewrite 模块指令可被执行时 就重写发起新一轮location 匹配
location / {
# 顺序执行如下两条rewrite指令
rewrite ^/test1 /test2;
rewrite ^/test2 /test3; # 此处发起新一轮 location 匹配 URI为/test3
}
location = /test2 {
return 200 “/test2”;
}
location = /test3 {
return 200 “/test3”;
}
# 发送如下请求
# curl 127.0.0.1:8080/test1
# /test3
如果正则表达regex式中包含 “}” 或 “;”,那么整个表达式需要用双引号或单引号包围。
示例 2:
location / {
rewrite ^/test1 /test2;
rewrite ^/test2 /test3 last; # 此处发起新一轮location匹配 uri为/test3
rewrite ^/test3 /test4;
proxy_pass http://www.baidu.com;
}
location = /test2 {
return 200 "/test2";
}
location = /test3 {
return 200 "/test3";
}
location = /test4 {
return 200 "/test4";
}
发送如下请求 curl 127.0.0.1:8080/test1 返回 /test3
当如果将上面的 location / 改成如下代码
location / {
rewrite ^/test1 /test2;
# 此处不会发起新一轮location匹配;当是会终止执行后续rewrite模块指令重写后的 URI 为 /more/index.html
rewrite ^/test2 /more/index.html break;
rewrite /more/index\.html /test4; # 这条指令会被忽略
# 因为 proxy_pass 不是rewrite模块的指令 所以它不会被 break终止
proxy_pass https://www.baidu.com;
}
发送请求 127.0.0.1:8080/test1
代理到 https://www.baidu.com
rewrite 后的请求参数:
如果替换字符串 replacement 包含新的请求参数,则在它们之后附加先前的请求参数。如果你不想要之前的参数,则在替换字符串 replacement 的末尾放置一个问号,避免附加它们。
# 由于最后加了个 ?,原来的请求参数将不会被追加到 rewrite 之后的 URI 后面*
rewrite ^/users/(.*)$ /show?user=$1? last;
rewrite_log 指令
语法:rewrite_log on | off;
默认值:rewrite_log off;
作用域:http 、 server 、 location 、 if
功能:开启或关闭以 notice 级别打印 rewrite 处理日志到 error log 文件。
set 指令
语法:set variable value;
默认值:none
作用域:server 、 location 、 if
定义一个变量并赋值,值可以是文本,变量或者文本变量混合体。
uninitialized_variable_warn 指令
作用域:http、 server 、 location 、 if
语法:uninitialized_variable_warn on | off;
默认值:uninitialized_variable_warn on
功能:控制是否记录 有关未初始化变量的警告。