Nginx

Nginx是什么

Nginx是一个Web服务器,也是个高性能方向代理服务器,Nginx起初为了解决基于进程模型产生的C10k问题,由俄罗斯lgor sysoev研发。

Nginxy有企业版本Nginx Plus,还有二次发行版Tengine,OpenResy(淘宝研发)

nginx反向代理支持两种协议 HTTP和MAIL

C10K 连接超过10K ,1W个请求,1M =100万个请求

Netcraft可以查看全球服务器Web服务器占有率。

传统上基于进程或线程模型架构的web服务通过每进程或每线程处理并发连接请求,这势必会在网络和I/O操作时产生阻塞,其另一个必然结果则是对内存或CPU的利用率低下。生成一个新的进程/线程需要事先备好其运行时环境,这包括为其分配堆内存和栈内存,以及为其创建新的执行上下文等。这些操作都需要占用CPU,而且过多的进程/线程还会带来线程抖动或频繁的上下文切换,系统性能也会由此进一步下降。

在设计的最初阶段,nginx的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级处理机制,nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在nginx中,连接请求由为数不多的几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。

如果负载以CPU密集型应用为主,如SSL或压缩应用,则worker数应与CPU数相同;如果负载以IO密集型为主,如响应大量内容给客户端,则worker数应该为CPU个数的1.5或2倍。

Nginx特性

模块化设计,较好的扩展性,早期不支持模块的动态装载和卸载

高可靠性,基于Master/Worker模式

支持热部署(平滑升级迁移),不停机的状态下更新配置文件,跟换日志文件,更新服务器程序版本

内存消耗低,10K个keep-alive连接模式下的非活动连接只消耗2.5M内存

支持event-driven事件驱动模型,AIO驱动机制,MMAP内存映射机制

Nginx基本功能

静态资源的web服务器,自身只能简单的接收和响应http

http协议的反向代理服务器

pop3,smtp imap4等邮件协议的反向代理

能缓存打开的文件(元数据缓存:文件的描述符等信息),能加快文件的打开速度

支持FastCGI(php-fpm),UWSGI 等协议机制,实现代理后端应用程序交互

支持过滤器,例如ZIP,SSI(服务端包含)

支持SSL加密机制

模块化(非DSO机制)

standard HTTP modules 标准(核心)HTTP模块:自动编译进程序不止一个
Optional HTTP modules 可选http模块
Mail modules 邮件模块
3rd party modules第三方模块,在编译时需手动指明加载方式加载

Nginx服务相关功能

虚拟主机,Keepalive,访问日志,日志缓冲(提高存取西能),URL重写,路径别名,访问控制(IP和用户),支持速率限制,并发限制

Nginx架构

Master/Worker模型:

一个master进程可以生成一个或者多个worker进程,每个worker基于事件驱动,响应用户请求, 其支持sendfile,sendfile64,这两种支持的文件大小不同

事件驱动:Linux(epoll),FreeBSD(kqueue),Solaris(/dev/poll)

除此之外配置了缓存时还会有缓存加载器进程cache loader和缓存管理器进程cache manager等,所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。

主进程Master以root用户身份运行,而Worker、Cache Loader和Cache Manager均应以非特权用户身份运行。

Master

加载,验证配置文件

创建,绑定,关闭套接字

管理worker进程(启动,终止,维护)

平滑重启(无需终止服务重载配置)

平滑升级(启用新的二进制程序并在需要时回滚到老版本)

重新打开日志文件,实现日志滑动

其他嵌入式perl,go脚本

Worker

响应客户端请求,提供HTTP服务和代理,提供FastCGI,uWSGI,SCGI等代理

Cache Loader

检查缓存存储中的缓存对象;

使用缓存元数据建立内存数据库;

Cache Manager

缓存的失效及过期检验;

Nginx安装

可使用yum或者源码方式安装

yum安装

yum方式很简单,直接使用yum源来安装

1
2
yum install nginx	#自动安装依赖关系
rpm -ql nginx #查找nginx安装生成的文件
源码安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
yum install -y pcre-devel openssl-devel zlib-devel
useradd nginx -s /sbin/nologin

#进入解压后的源码包路径,根据需求来定.
** 注意:`--with`都是启用模块,`--without`都是禁用模块 **

./configure \
--prefix=/usr \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--user=nginx \
--group=nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--with-http_ssl_module \ #使用ssl模块
--with-http_flv_module \ #使用flv流模块
--with-http_stub_status_module \ #使用监控模块
--with-http_gzip_static_module \ #使用gizp模块
--with-pcre #pcre模块启用
--with-file-aio #支持文件异步
--with-http_image_filter_module #支持图片过滤
--http-client-body-temp-path=/var/tmp/nginx/client/ \ #请求报文主体缓存目录
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \ #代理临时目录
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \ #fastcgi目录,支持php框架
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \ #uwsgi目录,支持python框架
--http-scgi-temp-path=/var/tmp/nginx/scgi \ #scgi目录,类似fastcgi另外一种机制

# make && make install
Nginx常用命令
1
2
3
4
nginx -t	#测试配置文件是否正确
nginx -s reload #nginx重载文件
nginx -V #nginx显示版本号,已经编译的那些模块
nginx --help查看更多帮助

配置文件说明

1
2
3
4
5
6
7
8
9
/etc/nginx/nginx.conf		#主配置文件
Include conf.d/*.conf
/etc/nginx/mime.types #所支持的MIME类型列表
/etc/nginx/fastcgi_params #fastcgi的配置文件
/etc/nginx/fastcgi.conf #与fastcgi_params一般只使用一个
/etc/nginx/uwsgi_params #与uwsgi框架的配置文件
/etc/nginx/scgi_params #cgi的配置文件
/etc/nginx/proxy.conf #代理的配置
/etc/nginx/sites.conf #配置虚拟主机的
主配置文件

/etc/nginx/nginx.conf 格式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
worker_process
error_log
user
events {
use epoll;
}
http {
access_log xxx;
upstream server{
server IP:PORT
}
server {
location URI {
driective <parameters>;
}
}
server {
....;
}
}
MAIN

该段落主要是配置Nginx运行启动时候必备参数 和 性能优化 以及 调试定位问题的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
user nginx;
worker_processes 1;
worker_cpu_affinity auto;
worker_rlimit_nofile 10240;
timer_resolution 100ms;
worker_priority 20;
error_log /var/log/nginx/error.log
events {
use epoll;
worker_connections 1024;
}
http:{
upstream server {
.....;
}
server {
...;
location / {
...;
}
}
}

user USERNAME
#指定nginx启动worker进程时 以什么用户启动

worker_processes NUMBER|auto
#启动worker个数
#如果负载以CPU密集型为主(比如SSL或压缩)则worker数应与CPU数相同;如果以IO密集为主(如大量内容给客户端),则worker数应是CPU的1.5或2倍

worker_cpu_affinity auto|CPUMASK
#根据物理cpu自动绑定,worker不使用进程或者线程处理请求,而是直接将worker绑定到CPU上,这样就没有进程切换这一说法
#worker_processes 4;
#worker_cpu_affinity 0001 0010 0100 1000;

worker_rlimit_nofile NUMBER
#设置worker进程打开文件数量,worker_rlimit_nofile需要大于等于woker_connections的大小

timer_resolution INTERVAL
#用于降低gettimeofday()系统调用的缓存时钟,默认情况下,每次从kevent(),epoll,/dev/poll,select(),poll都会执行此系统调用

worker_priority [-20~19]
#设置worker进程优先级,官方说明一般在-20到19之间,如果想要woker运行快优先级可调到20

error_log PATHFILE
#配置错误日志,改参数可用于main,http,server,已经localtion上下文中.

events事件驱动I/O框架

use [ kqueue | rtsig | epoll | /dev/epoll | select | poll | eventport ]
#根据当前系统内核版本设置适合自己的事件模型。
#kqueue freeBSD 4.1+
#epoll linux2.6+
#/dev/epoll solaris 7 11/99+

worker_connections NUMBER
#事件驱动每个worker支持的连接数,如果worker_process为2,那么服务器最大支持2048个连接
#当nginx作为web服务时 最大客户端处理数max_clients = worker_processes * worker_connections
#当nginx作为反向代理时 最大客户端处理数max_clients = worker_processes * worker_connections/2
#这里的max_clients很多人都疑惑为什么有人认为max_clients = worker_preocesses * worker_connections/4呢?
#如果max_clients指的是建立连接最大客户数,由于每个游览器默认两个并发连接,那么nginx作为反向代理是/4
#如果max_clients指的是处理客户端数,那就nginx作为反向代理是/2

server_tokens off;
#隐藏版本号
HTTP

HTTP上下文配置用于http的各模块,此类指令很多,每个模块都有专用指令,具体参考nginx官方wiki模块部分的说明。大致上这些模块所提供的配置指令还可以分为以下几个类别:

1
2
3
4
5
6
7
客户端指令:client_body_buffer_size,client_header_buffer_size,client_header_timeout,keepalive_timeout...

文件IO指令:aio,directio,open_file_cache,open_file_cache_min_uses,open_file_cache_valid,sendfile....

hash类指令:用于定义Nginx为特定的变量分配多大的内存空间,如types_bash_bucket_size,server_name_hash_bucket_size,variables_hash_bucket_size

套接字指令:用于定义Nginx如何处理TCP套接字相关的功能,如tcp_nodelay(用于keepalive功能启用)和tcp_nopush(用于sendfile启用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
...;
http {
include mime.types;
default_type application/octet-stream;
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;
#send_time #;
#sendfile on;
#tcp_nopush on;
tcp_nodeplay on
keepalive_timeout 65;
keepalive_requests 100;
#keepalive_disable none | browser;
#client_body_buffer_size SIZE(8|16K);
#client_body_temp_path [LEVEL1 [LEVEL2 [LEVEL3]]];
#aio on;
#directio off;
#open_file_cache off;
#open_file_cache errors off;
#open_file_cache_valid TIME;
#open_file_cache_min_uses NUMBER;

upstream name {
server 192.168.1.10:8080
keepalive 300
}
server {
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}

include mine.types
#指定包含文件类型,mine.type里面定义,如html,css,gif,jpeg,js,txt....

default_type application/octet-stream
#默认是octet-stream,如果一个文件在mime.types没定义,就使用默认的类型octet-stream,这个表示下载,
#如果设置default_type text/html;则表示可以在游览器查看

log_format main string
#设定log日志格式以及名称,main可以随便定义,string必须是nginx可识别的变量,可以自定义变量
#$remote_addr,$http_x_forwarded_for #客户端的ip地址;
#$remote_user #客户端用户名称;
#$time_local #访问时间与时区;
#$request #请求的url与http协议;
#$status #请求状态,200,302,404,500等,
#$body_bytes_sent #发送给客户端文件主体内容大小;
#$request_body #请求体
#$http_referer #从那个页面链接访问过来的;
#$http_user_agent #客户浏览器的相关信息;

access_log path format_name
#设定访问日志路径,使用哪个名称日志格式。
#还有设置缓存大小刷新时间间隔,以及定义缓冲提升nginx性能
#open_log_file_cache max=N [inactive=time] [min_uses] [valid=time]
#open_log_file cache off;
#max 设置缓存中描述符最大数量,如果缓存占满,最近最少使用(LRU)的描述符被关闭
#inactive 设置缓存文件描述符在多长时间内没有被访问就关闭; 默认为10秒。
#min_uses 设置在inactive参数指定的时间里, 最少访问多少次才能使文件描述符保留在缓存中;默认为1。
#valid 设置一段用于检查超时后文件是否仍以同样名字存在的时间; 默认为60秒。
#off 禁用缓存。

send_time #;
#发送响应报文的超时时长,默认60s

sendfile on|off
#在内核完成后直接封装响应客户端(支持小文件) sendfile64(支持大文件)
#普通响应步骤client--->网卡(内核)--->用户空间(worker进程80套接字)--->内核空间(系统调用)--->复制--->用户空间--->内核(复制)-->client
#senfile响应client--->网卡(内核)--->用户空间(worker进程80套接字)--->内核空间(系统调用)--->复制--->client
#但是如果使用file aio模块,必须禁用sendfile支持

tcp_nopush on
#不做推送,在开启sendfile才有效,它和tcp_nodeplay互斥,TCP_CORK是linux下tcp/ip传输的一个标准(一般情况下tcp交互中,当程序收到数据包后马上传送不等待,而TCP_CORK选项是数据包不会传送出去,等到数据包最大时一次性传输,有助于解决网络拥堵),在tcp_nopush on时候,才会设置TCP_CORK方法,该选项对于www.ftp等大文件才有帮助。在FreeBSD使用TCP_NOPUSH套接字,在Linux使用TCP_CORK套接字,详见Nagle算法

tcp_nodeplay on
#对于keepalive模式下连接是否使用tcp_nodelay选项,默认关闭,其功能类似tcp_nopush,将多个小报文合并成一个报文一起发送,提高宽带利用率,将发往同一个主机很小的TCP报文合并成一个,实际生产对于用户请求即使浪费带宽也不能合并请求

keepalive_timeout 75 75
#长链接超时时间,0表示禁用,默认为75s,请求完成后还需要保持多久连接,目的是减少创建连接过程给系统带来的耗损,通常默认足够,如果内部服务器通讯场景过大建议增大。
#第一个75设置keep-alive客户端连接在服务端保持开启超时时间,第二个75可选,在客户端响应的header区域中设置一个"keep-alive:timeout=time"
#当nginx作为反向代理时候,为了支持场链接
#从client到nginx 和 nginx到server连接都需要设置长连接
#例子
http {
keepalive_timeout 75
upstream www {
server 192.168.0.1:8080;
server 192.168.0.2:8080;
keepalive 300;
server {
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}
#upstream 中的keepalive,设置upstream服务器的空闲keepalive连接最大数量,当数量被突破时,最近使用最少连接将被关闭,keepalive指令不会限制一个nginx worker进程到upstream服务器连接的总数量。
#HTTP协议对长连接支持从1.1版本后才有,需要通过proxy_http_version指令设置为1.1
#而Connection header应该被清理,清理从客户端过来的http header,因为即使是客户端和nginx之间是短连接,nginx和upstream之间也是可以开启长连接。所以需要清理客户端请求中的"Conection" header

keepalive_requests
#在keepalive连接上允许请求的最大资源数量,默认为100,当一个keepalive建立后,nginx就会为这个连接设置一个计数器,记录这个keepalive长链接上已经接受并处理的客户端请求数量,如果达到这个参数设置最大时,nginx会强行关闭这个长链接,使客户端重新建立新的场链接。
#大多数情况下QPS不是很高,100足够,但是对一些QPS高比如(10000QPS,甚至更高)100显的太低,
#QPS=10000时候,客户端每秒发送10000个请求(通常建立长链接),每个连接最多跑100次请求,意味着每秒就有100个长连接因此被nginx关闭。同样意味着为了保持QPS,客户端不得不每秒重新新建100个连接,从而导致大量TIME_WAIT的socket链接,因此对于QPS较高场景,很有必要加大这个设置,避免出现大量连接被生成在抛弃。

#出现大量TIME_WAIT情况
#nginx出现大量TIME_WAIT情况有两种
#keepalive_request设置较小,高并发超过此值后nginx悔强制关闭客户端保存keepalive长连接;(主动关闭连接后导致nginx出现TIME_WAIT)
#keeaplive设置比较小(空闲数小),导致高并发nginx会平凡出现连接数抖动(超过该值会关闭连接),不停关闭\开启和后端server保持的keepalive长连接
#后端server端出现大量TIME_WAIT情况
#nginx没有打开和后端长连接,即使设置proxy_http_version 1.1和proxy_set_header Connection "" ;从而导致后端server每次关闭连接,高并发出现server端大量TIME_WAIT。

keepalive_disable none|browser;
#禁止那些游览器不使用keepalive功能,如果keepalive_disable msie6,禁止ie6不使用keepalive功能

client_body_buffer_size;
#接受客户端请求报文body的缓存区大小,默认为16k,在32位系统上是8k,超出指定大小将移存在磁盘上

client_body_temp_path [Level1 [level2 [level3]]]
#设定与存储客户端请求body临时存放路径以及子目录结构和数量
#例子
client_body_temp_path /var/tmp 2 2;
#说明椅子子目录使用2个字符表示,二级目录下用2字符表示,每级目录都有256个文件夹,采用16进制表示文件,1个字符最多表示16,2字符表示256

aio on;
#是否启用异步IO模式,可用于HTTP,SERVER,LOCATION上下文,sendfile不能与AIO同时使用

directio SIZE|off;
#当大于SIZE的时候是否直接IO操作,不存在内存缓冲,直接从硬盘加载使用,用于HTTP,SERVER,LOCATION上下文中

open_file_cache off | max=N [inactive=time];
#对打开文件缓存.主要包括:文件描述符,文件大小,最近修改时间,目录结构,没有找到或者没有权限操作文件相关信息,
#max=N,可缓存的最大条目上限,一旦达到上限, 则会使用LRU算法从缓存中删除最近最少使用的缓存项
#inactive=time : 在此处指定的时长内没有被访问过的缓存项识别为非活动缓存项, 因此直接删除

open_file_cache errors on|off;
#是否缓存找不到其路径的文件,或没有权限访问的文件相关信息

open_file_cache_valid TIME;
#每隔多久检查一次缓存中缓存项的有效性,默认为60秒

open_file_cache_min_uses NUMBER;
#缓存项在非活动其限内最少应该被访问的次数
UPSTREAM

upstream模块可定义一个新的上下文,位于server之上http之下,包含一组upstream服务器,这些服务器可能被赋予不同权重,不同类型,设置可以基于维护原因被标记为down。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
http{
...;
upstream myserver {
service 192.168.1.10:8080 wight=5 max_fails=3 file_timeout=6;
service 192.168.1.10:8090 wight=5 max_fails=3 file_timeout=6;
service 192.168.1.20:8080 backup;
service 192.168.1.30:8080 down;
ip_hash;
keepalive 300;
}
service {
..;
location {
..;
}
}
}

upstream模块常用的指令有:

round-robin
#轮询发往后端默认为轮轮询

ip_hash
#基于客户端IP地址完成请求的分发,它可以保证来自于同一个客户端的请求始终被转发至同一个upstream服务器

least_conn
#最少连接调度算法

keepalive
#每个worker进程为发送到upstream服务器的连接所缓存的个数.

server:定义一个upstream服务器的地址,还可包括一系列可选参数,如:
weight: 权重;
max_fails: 最大失败连接次数,失败连接的超时时长由fail_timeout指定;
fail_timeout: 等待请求的目标服务器发送响应的时长;
backup: 用于fallback的目的,所有服务均故障时才启动此服务器;
down: 手动标记其不再处理任何请求;
SERVER

用于定义虚拟服务器相关的属性,位于http上下文,常见的指令有backlog、rcvbuf、bind及sndbuf等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
....;
http {
....;
upstream {
...;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
root /www;
location / {
....;
}
}

listen [:port] | [default_server] | [ssl] [http2 | spdy];
#监听端口,如果有多块网卡可以使用listen 192.168.1.2:80
#ssl 用于限制只能通过SSL连接提供服务,不是以端口确认其协议,需要启用SSL,需要在监听的端口后面, 添加ssl选项。
#http2 支持http version2,需要在nginx编译时开启http2协议支持
#spdy google研发的http协议,比http1.1性能好。全称speedy,在编译时编译了spdy模块情况下,用于支持spdy协议

server_name localhost;
#服务名称或者域名,支持正则表达式匹配*.baidu.com 或者 ~^.*.baidu.com$

charset koi8-r;
#字符集设置

access_log PATH main;
#日志路径,以及使用哪个日志格式

root /www;
#设置web资源路径映射,用于指明请求url所对应的文件目录路径,可用于server或者location中
LOCATION

通常位于server上下文,用于设定某URI的访问属性,location也可以嵌套,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
....;
http {
....;
upstream {
...;
}
server {
...;
location / {
root html;
index index.html;
try_files index.html /images/test1.html;
}
location /images/ {
alias /data/imgs/;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

location = /50x.html {
root html;
}
}
}

root html;
#定义url路径,这里是绝对路径,nginx下的html目录,当访问daemon.com/时候访问的是nginx下的html目录

index index.html;
#定义默认主页(nginx_http_index_module模块引入),可定义在http,server,location

try_files $uri $uri/ /index.php?$args;
#可用于server和location中,尝试查找第1到最后一个文件,如果第一个不存在跳转到下一个,必须确保最后一个存在,如果不存在则会导致死循环。

alias /data/imgs;
#只能用于location配置段,定义路径别名

root和alias区别:
location /imags/ {
root /data/imgs/;
}

location /imags/ {
alias /data/imgs/;
}
root指令:给定的路径对应location的"/",这个URI
/imags/test.jpg --> /data/imgs/imags/test.jpg
alias指令:路径为对应的location的"/url/"这个URI
/imags/test.jpg --> /data/imgs/test.jpg

error_page code $uri;
#定义错误页面,根据http状态码重写向错误页面
#实例:
error_page 404 /404.html;
如果页面返回404就以404.html页面返回,状态码是404
error_page 404 = /404.html;
如果页面返回404就以404.html页面返回,状态码是200
location说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
location语法格式:
location [ = | ~ | ~* | ^~ ] url { ...}
= URI的精确匹配
~ 做正则表达式匹配,区分字符大小写
~* 做正则表达式匹配,不区分字符大小写
^~ URI的左半部分匹配,不区分字符大小写
!~,!~* 区分大小写不匹配,不区分大小写不匹配

#允许根据用户请求的URI来匹配定义的各location,匹配到时, 此请求将被相应的location块中的配置所处理。
#简言之:用于为需要用到专用配置的uri提供特定配置,当匹配多次时,其匹配优先级为:精确匹配=,^~,~或~*,不带符号的URL, 如果优先级都一样, 就匹配最精确的规则
#优先级:
location = / {
[configuration A]
}
location / {
[configuration B]
}
location /documents/ {
[configuration C]
}
location ^~ /images/ {
[configuration D]
}
location ~* \.(gif|jpg|jpeg)$ {
[configuration E]
}

#例子:
location ~ /\.ht {
deny all;
}
#当访问.htaccess文件时候拒绝所有

location ~ \.php$ {
root /xxx;
fastcgi_pass 127.0.0.1:9000;
}
#将所有php文件推送到php-fpm

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ {
...;
}
#匹配gif|jpg|jpeg|png|bmp|swf|js|css结尾文件

location 后面"/"和没有"/"的区别
#看个例子
如果域名是www.zhuxyid.com,访问www.zhuxyid.com/helloworl的话
location /hello { #这里能匹配到
root xxx;
}

location /hello/ { #这里则不能匹配
root xxx;
}
Nginx If判断

在location中使用if语句可以实现条件判断,其通常有一个return语句,且一般与有着last或break标记的rewrite规则一同,防盗链模块使用。但其也可以按需要使用在多种场景下,需要注意的是,不当的使用可能会导致不可预料的后果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#if语句中的判断条件
#正则表达式匹配:
~ 与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
~* 与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
!~ 与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
!~* 与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;

#文件及目录匹配判断:
-f, !-f 判断指定的路径是否为存在且为文件;
-d, !-d 判断指定的路径是否为存在且为目录;
-e, !-e 判断指定的路径是否存在,文件或目录均可;
-x, !-x 判断指定路径的文件是否存在且可执行;


#例子:
http {
upstream imageserver{
server 192.168.0.10:80;
server 192.168.0.11:81;
}
server {}
location / {
if ($request_method == “PUT”) { #如果客户端方法是PUT,就代理到0.11上,有点读写分离的感觉。
proxy_pass http://192.168.0.11:8021;
}
if ($request_uri ~ "\.(jpg|gif|jpeg|png)$") {
proxy_pass imageservers;
break;
}
}
}

实例:
#cookie首部检测匹配
if ($http_cookie ~* "id=([^;]+)(?:;l$)") {
set $id $1;
}

#请求报文的请求方法是POST,返回405
if ($request_method = POST) {
return 405;
}

#限速
if($slow) {
limit_rate 10k;
break;
}

#非法引用,返回403,注:也可以对非法引用到其它页面
if($invalid_referer) {
return 403;
}

#根据IE类型重写
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}

returncode [text];
returncode URL
return URL;
#return:立即停止对请求的URI的处理,并返回指定的状态码

set $variable value;
#set:设定变量值,或者自定义变量

rewrite_log on | off;
#是否将重写日志记录errorlog中,默认为关闭(调试方法:错误日志debug,并开启rewrite_log)
Nginx全局变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri

Nginx反向代理

Nginx通过proxy模块实现反向代理功能。在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上。

反向代理:正对外部网络,如果客户端访问某个网站,但该网站不提供页面,只把请求代理只后端,在从后端返回至代理,在响应给客户端,该代理称作反向代理。

正向代理:针对内部网络,如果客户端不能访问外网,需要设置通过某台机器代理至外网,外网结果返回至代理机,在返回给客户端,该代理称作正向代理。

透明代理:针对内部网络,不需要设置任何代理服务器地址,但是需要将网关指向代理服务器。

参考:Nginx proxy中文文档

proxy模块指令

proxy模块的可用配置指令非常多,它们分别用于定义proxy模块工作时的诸多属性,如连接超时时长、代理时使用http协议版本等.下面对常用的指令做一个简单说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
proxy_pass [domain | ip | upstream_name]|:PORT;
#将location代理到哪里,这里可以是域名,IP,upstream名称,可以加端口,应用于Location上下文
#这里值得注意:
#当proxy_pass后有"/"时候,相当于绝对根路径,不会将location 中匹配的路径代理走
#当proxy_pass后没有"/"时,会把location中部分路径代理走
#示例:
#访问:http://www.aaa.com/abc/index.html,配置如下
location /abc/ {
proxy_pass http://127.0.0.1:8080/;
}
#会代理到:http://127.0.0.1:8080/index.html
location /abc/ {
proxy_pass http://127.0.0.1:8080;
}
#会代理到:http://127.0.0.1:8080/abc/index.html
location /abc/ {
proxy_pass http://127.0.0.1:8080/dev;
}
#会代理到: http://127.0.0.1:8080/devindex.html;
localtion /abc/ {
proxy_pass http://127.0.0.1:8080/dev/;
}
#会被代理到: http://127.0.0.1:8080/dev/index.html;

proxy_pass_header field;
#传递头部给后端服务器

proxy_hide_header field;
#设定发送给客户端的报文中需要隐藏的首部

proxy_set_header field value;
#用于向后端服务器发请求报文时,将某请求首部重新赋值,或在原有值后面添加一个新的值
#示例:
proxy_set_header HOST $http_host;
#将$http_host传递给HOST变量, 在nginx向后端发请求时,加入HOST首部
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#将客户端的真实IP地址赋值给X-Forwarded-For变量,在nginx想后端发时加入X-Forwarded-For变量,
#如果中间有多层代理,每经过一层代理时,代理服务器都会将在后面增加自己的IP地址,并以分号分隔

proxy_redirect;
#重写location并刷新从后端收到报文首部

proxy_connect_timeout;
#nginx将一个请求发送到后端之前等待最大时长

proxy_send_timeout;
#在连接断开之前两次发送到后端的写操作的最大间隔时长

proxy_rend_timeout;
#在连接断开之前两次发送到后端接受操作的最大间隔时长

proxy_cookie_domain;
#发往后端时SET-COOKIE首部设定的domain属性修改为指定的值,可以设置为字符串,正则表达式模式或者一个引用变量

proxy_cookie_path;
#发送后端时通过SET-COOKIE首部设定的PATH属性修改为指定的值
proxy缓冲

nginx在默认情况下在将其响应给客户端之前会尽可能地接收来upstream服务器的响应报文,它会将这些响应报文存暂存于本地并尽量一次性地响应给客户端。然而,在来自于客户端的请求或来自upsteam服务器的响应过多时,nginx会试图将之存储于本地磁盘中,这将大大降低nginx的性能。因此,在有着更多可用内存的场景中,应该将用于暂存这些报文的缓冲区调大至一个合理的值。

1
2
3
4
5
6
7
8
proxy_buffer_size size
#设定用于暂存来自于upsteam服务器的第一个响应报文的缓冲区大小;

proxy_buffering on|off;
#启用缓冲upstream服务器的响应报文,否则,如果proxy_max_temp_file_size指令的值为0,来自upstream服务器的响应报文在接收到的那一刻将同步发送至客户端;一般情况下,启用proxy_buffering并将proxy_max_temp_file_size设定为0能够启用缓存响应报文的功能,并能够避免将其缓存至磁盘中;

proxy_buffers 8 4k|8k
#用于缓冲来自upstream服务器的响应报文的缓冲区大小;
proxy缓存

nginx做为反向代理时,能够将来自upstream的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
proxy_cache_path PATH [levels=levels] keys_zone=name:size [inactive=time][max_size=size];
#定义缓存,设置缓存名称,缓存路径,缓存大小等。只能用于HTTP上下文
#实例:
proxy_cache_path /data/nginx/cache/img levels=1:2:1 keys_zone=my_img:20m max_size=10g;
#levels=1:2:1 #表示一级目录1个字符,二级目录2个字符,三级目录1个字符,最多只能设置3级
#keys_zone=my_img:20m #存储键区域大小
#max_size=1g #/img目录空间上限1G,当缓存对象超出时候,采用LRU清理,谁用的少清理谁
#inactive #非活动缓存项从缓存中剔除之前的最大缓存时长
#loader_files #缓存加载器每次工作过程最多为多少个文件加载器
#loader_sleep #缓存加载器的每次迭代工作后的睡眠时长
#loader_threashold #缓存加载器的最大睡眠时长

proxy_cache NAME;
#调用设置的缓存名称,必须实现设定好缓存

proxy_cache_lock
#在缓存未命中阻止多个相同的请求同时发往后端,其生效范围是worker级别

proxy_cache_lock_timeout
#proxy_cache_lock功能锁定时长

proxy_cache_min_uses
#某响应报文被缓存之前至少应该被请求次数

proxy_cache_use_stale
#在无法连到upstream服务器时候那种情况(error,timeout,http_500)让nginx本地缓存过期的缓存对象之间响应给客户端
#实例
proxy_cache_use_stable error|timeout|invalid_header|updating|http_50[1~4]|http_404|off

proxy_cache_valid
#用于为不同响应设定不同时长的有效缓存时长
#实例
proxy_cache_valid 200 302 10m;
#设定状态为200和302的缓存时长为10分钟

proxy_cache_methods [GET|POST|HEAD];
#为那些方法启用缓存功能.

proxy_cache_bypass STRING;
#设置那种情况下,nginx不从缓存读取数据
#实例
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass $http_pragma $httpp_authorization;

#配置实例
http {
proxy_cache_path /data/nginx/cache levels=1:2:1 keys_zone=MYHTML:10m inactive=24h max_size=1g;
upstream my_web {
server 172.16.0.2:8080;
server 172.16.0.2:8081;
}
server {
location / {
proxy_pass http://my_web;
proxy_set_header Host $host;
proxy_cache MYHTML;
proxy_cache_valid 200 1d;
proxy_cache_valid 301 302 10m;
proxy_cache_vaild any 1m;
}
}
}

Nginx常用模块

nginx-limit模块

ngx_http_core_module,ngx_http_limit_conn_module,ngx_http_limit_req_module中的limit相关参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
limit_except METHOD {...};
#对指定范围之外的其它方法进行访问控制,应用于location上下文
#例子
limit_except GET {
allow 172.16.0.0/16;
deny all;
}

limit_rate SPEED;
#限制客户端每秒种所能够传输的字节数, 默认为0,表示不限制,应用于http,server,location,if in location上下文中
#例子
server {
if ($slow) {
set $limit_rate 4k;
}
}

limit_rate_after SIZE;
#超出SIZE的值, 就限制速度,应用于http,server,location,if in locataion上下文中
#例子
location /flv/ {
limit_rate_after 500k;
limit_rate 50k;
}
访问控制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#allow和deny可用于http,server,location上下文中

allow address | CIDR | UNIX | ALL;
#允许那些地址可以是网络地址

deny address | CIDR | UNIX | ALL;
#拒绝,同上

例子:
location / {
allow 172.16.0.2;
allow 192.168.1.0/24;
allow 2018:abc8::22;
deny 172.16.0.1;
deny all;
}
基本认证模块
1
2
3
4
5
6
7
8
9
10
11
auth_basic STRING;
#定义认证名称,主要是提示作用.认证时显示提示信息

auth_basic_user_file FILE;
#用户认证的用户账号文件
#格式:
user1:pwd1
user2:pwd2
#也可以直接使用httpd程序提供的htpasswd生成
#htpasswd -c -m /www/.htpasswd user1
#>pwd输入密码
自定义头信息
1
2
3
4
5
6
7
8
add_header_name value [always]
#向响应报文添加自定义首部,并为其赋值,应用上下文为http,server.localtion中
#例子
add_hreader Via $server_addr

expires [modified] time;
expires epoch | max | off
#允许或者禁止向响应报文的cache-control或者expires首部添加新值或修改其值
nginx状态功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#stub_statu功能,编译时添加--with-http_stub_status_module选项
#实例
location /my_ngx_monitor {
stub_status on;
allow 172.16.0.100;
deny all;
}
#访问http://www.zhuxyid.com/my_ngx_monitor
Active connections: 1
server accepts handled requests
2 2 18
Reading: 0 Writing: 1 Waiting: 0

#active connections:当前活动客户端连接数(包括等待)
#accepts:已接受客户端连接总数量
#handled:已处理完成的客户端连接请求总数量
#requests:客户端总的请求数
#reading:当前正在读取客户端请求报文首部信息的数量
#writing:当前正在向客户端发送响应报文的链接数量
#wating:长连接模式的保持连接个数,或者活动连接个数(reading+writing)
nginx防盗链模块

基于请求报文中的referer首部的值, 做访问控制 ,可以防止盗链,其只应用于server,location上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
referer_hash_bucket_size SIZE;
#可以放多个缓存我要上,默认是64
referer_hash_max_size SIZE;
#默认2048
valid_referers none|blocked|server_names|string...;
#none : 请求的报文不存在referer首部
#blocked : 请求报文中存在referer首部,但其没有有效值,或其值非以http://或https开头
#server_names :其值为一个主机名
#arbitrary string : 直接字符串,可以使用*号匹配
#rugular expression : 以~起始的正则表达式

#注意: 内置变量:$invalid_referer(所有不能符合valid_referer指定定义的引用请求均为不合法引用),需要加上条件判断语句

#示例:
valid_referers none blocked server_name *.example.com example.* www.example.org/aglleries/ ~\.google\.;
if ($invalid_referer) {
return 403;
}
nginx重写模块

将请求的url基于正则表达式进行重写(URL重定向),

在如下情况下可以使用:

http转换成httpd服务(http —- https)

域名转换domain.tld —-domain2.tld,

URL转换uri1—-url2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
rewrite regex replacement [flag];
#应用于server,location,if上下文

regex:基于PERL的正则表达式,用于匹配用户请求的URL;
replacement:重写重定向的结果
flag:标志位[last|break|redirect|permanent]

#regex:
PCRE正则表达式元字符:
字符: .,[],[^]
次数: *,+,?,{m},{m,}{m,n}
位置锚定: ^,$
或者: |
分组: (), 后向引用: 2,…..

#flag:
last #重写完成之后停止对当前uri的进一步处理,改为对新uri的新一轮处理(对URI的重写规则进行匹配,当检查到第一条匹配到的时候,进行重写.然后返回到重写规则的第一条位置进行重新匹配,如果有匹配到的再进行重写,默认只能10次匹配). 此过程用户端感受不到.
break #对URI的重写规则进行匹配,只要匹配到就重写,不再进行再次匹配,此过程用户端感受不到.
redirect #重写完成之后返回客户端一个临时重定向,由客户端对新的URI重新发起请求, 即302的状态码
permanent #重写完成之后,会返回客户端一个永久的重写向,由客户端对新的URI重新发起请求,即301的状态码
nginx ssl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
listen 443;
#监听端口

server_name www.zhuxyid.com;
#ssl主机的FQDN名称

ssl_certificate cert.pem;
#ssl的公钥

ssl_certificate_key cert.key;
#ssl的私钥

ssl on | off;
#启用或关闭ssl,若不在listen处定义,也可以在server{ }中定义ssl on; 来启用https服务

ssl_session_cache off | none | [builtin[:size]] [shard:name:size];
#默认使用shared模式
#off : 禁止缓存 ,关闭缓存,不支持缓存功能
#none :禁止缓存 ,不响应缓存
#builtin : 使用openssl内置的ssl会话缓存 ,此机制为各worker私有
#shared: 在各worker之间使用一个共享的缓存,name:独有名称,size:缓存空间大小, 默认为1M,可以调到10M
示例:
ssl_session_cache shared:ssl:1m;

ssl_session_timeout 5m;
#ssl会议超时时长,即ssl session cache中的缓存有效时长,默认为5m

ssl_protocols [sslv2][sslv3][tlsv1][tlsv1.1][tlsv1.2];
#使用哪些协议版本, 默认为TLSv1,TLSv1.1,TLSv1.2
#ssl_protocols SSLv2 SSLv3 TLSv1;

ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ciphers CIPHERS
#nginx使用的加密算法

ssl_prefer_server_ciphers on;
#依赖SSLv3和TLv1协议的服务器密码将优先于客户端密码

ssl_buffer_size SIZE;
#ssl缓冲大小

ssl_client_certificate file;
#需要验证客户端证书

ssl_crl FILE;
#证书吊销列表

ssl_trusted_certificate FILE;
#信任的根证书

#配置实例
a.创建系统私钥
(umask 077; openssl genrsa 2048 > /PATH/cakey.pem)

b.生成系统自签证书
openssl req -new -x509 -key /PATH/cakey.pen -out cacert.pem
一次输入:CN,JS,NJ,zhuxyid,it,ca.zhuxyid.com,caadmin@zhuxyid.com

c.创建serial index.txt
echo 01 > serial & touch index.txt & cd nginx/ssl/

d.创建私钥
(umake 077;openssl genrsa 1024 > nginx.key)
openssl req -new -key nginx.key -out nginx.csr
依次输入:CN,JS,NJ,zhuxyid,it,www.zhuxyid.com
openssl ca -in nginx.csr -out nginx.crt -days 3650

more nginx.conf
server {
listen 443;
server_name www.zhuxyid.com;
ssl on;
ssl_certificate /ssl/nginx.crt;
ssl_certificate_key /ssl/nginx.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
listen 443;
location / {
root html;
index index.html index.htm;
}
}
/usr/local/nginx/sbin/nginx -s reload
#这里只是测试用,如果是外网需要向权威机构申请证书,freessl.org
nginx压缩模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
gzip on|off
#开启压缩,通常位于http上下文

gzip_comp_level [1-9]
#压缩比率,默认为1,越大越占用cpu使用率

gzip_types mine.types
#指名对那些类型资源进行压缩

gzip_disable msie6;
#根据游览器来设置是否压缩,这里是ie6不开启压缩

gzip_min_length 0
#设置允许压缩页面最小字节数,页面字节从header头中的content-length获取,默认值0,不管页面多大都会被压缩,通常设置大于1k字节,小于1k可能越压越大,比如本身10字节,压缩一下反而大了,噗噗噗


#实例:
http {
gzip on;
gzip_comp_level 6;
gzip_disable msie6;
gzip_types text/plain text/css text/xml application/x-javascript application/xml application/json application/java-script;
gzip_min_length 2;
}

小结

对于nginx模块还有很多很多,以上是最基础的一些安装配置说明,后期还需要总结关于nginx的一些奇淫技巧

看完了?赏个鸡腿钱,谢谢老板!