写在前面

考虑到Nginx主配置文件的重要性和日常使用的高频率,这里专门拿出一篇文章来深入学习nginx.conf主配置文件,灵活配置nginx.conf主配置文件是学好Nginx的关键所在。

Nginx配置文件

在nginx目录下有一个conf目录,里面存放的都是与Nginx配置相关的文件,一般来说我们修改的都是名为nginx.conf的主配置文件。该配置文件由若干个部分组成,每个大括号{}表示一个部分,每行指令都由分号结束;,用于表示一行的结束。
去除nginx.conf主配置文件中的注释代码,完整的内容如下所示:

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
worker_processes  1;

events {
worker_connections 1024;
}

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;
}
}

使用类似于tree的命令来生成该配置文件内容的树形图,如下所示:

1
2
3
4
5
6
7
8
9
10
11
main        # 全局配置,对全局生效
├── events # 配置影响Nginx服务器或与用户的网络连接(项工作模式设置)
├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置(http设置)
│ ├── upstream # 配置后端服务器具体地址,需要使用负载均衡时必须配置(负载均衡设置)
│ ├── server # 配置虚拟主机的相关参数,一个http块中可以有多个server块(主机设置)
│ ├── server
│ │ ├── location # server块可以包含多个location块,location指令用于匹配uri(URL设置)
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...

先从整体层面来学习这个Nginx配置文件,通常的配置语法规则如下:
(1)配置文件由指令和指令块构成;
(2)每条指令以;分号结尾,指令与参数间以空格符号分隔;
(3)指令块与{}大括号将多余条指令组织在一起;
(4)include语句允许组合多个配置文件以提升可维护性;
(5)使用#符号添加注释,提高可读性;
(6)使用$符号使用变量;
(7)部分指令的参数支持正则表达式。

常用正则介绍

从上面的介绍中可以看到,server块中可以包含多个location块,location指令用于匹配uri,语法如下:

1
2
3
location [ = | ^~ | ~ | ~* ] uri {
...
}

简单解释一下上述代码的含义:location是指令;[ = | ^~ | ~ | ~* ]是匹配的标识符;uri是匹配的网站地址;{...}是匹配URI后要执行的配置段。

这里对指令后面匹配的标识符进行介绍,如下:
(1)=精确匹配路径,用于不包含正则表达式的uri前,如果匹配成功,那么就不再进行后续的查找;
(2)^~用于不包含正则表达式的uri前,表示如果该符号后面的字符是最佳匹配,则采用该规则,不再进行后续的查找。


(3)~表示用该符号后面的正则去匹配路径,区分大小写
(4)~*表示用该符号后面的正则去匹配路径,不区分大小写
(5)/是通用匹配,任何请求都会匹配到。

也就是说如果uri中不包含正则表达式,则可以使用前面两个;如果包含则必须使用后面两个。

当然常用的正则如下表所示:
正则|说明|
-|:-:|
.|匹配除换行符以外的任意字符|
?|匹配0次或者1次|
+|匹配1次或者多次|
*|匹配0次或者多次|
\d|匹配数字,即0-9|
\D|匹配非数字,即不是数字|
^|匹配字符串的开始|
$|匹配字符串的结束|
{n}|重复n次|
{n,}|重复n次或多次|
[c]|匹配单个字符c|
[a-z]|匹配a-z小写字母中的任意一个|

由于location后面的标识符非常重要,后续会专门出一篇文章来研究它的用法。

全局变量

当然除了可以使用正则表达式外,还可以使用一些常用的全局变量,开发者可以在配置的任意位置使用它们:

全局变量名 功能介绍
$host 请求信息中的Host,如果请求中没有Host行,则等于设置的服务器名,注意不包括端口
$request_method 客户端请求类型,如 GET、POST
$args 请求中的参数
$arg_PARAMETER GET 请求中变量名PARAMETER参数的值,如$http_user_agent就表示User-Agent 的值
$content_length 请求头中的Content-length字段的值
$content_type 请求头中的Content-Type字段的值
$http_user_agent 客户端agent信息
$http_cookie 客户端cookie信息
$remote_addr 客户端的IP地址
$remote_port 客户端的端口
$remote_user 已经经过Auth Basic Module验证过的用户名
$server_protocol 请求使用的协议,如 HTTP/1.0、HTTP/1.1
$server_addr 服务器地址
$server_name 服务器名称
$server_port 服务器的端口号
$scheme HTTP 方法(如http,https)
$uri 不带请求参数的当前URI,注意$uri中不包含主机名,如/envy/index.html
$document_uri 功能与$uri类似
$document_root 当前请求在root指令中指定的值
$request_uri 包含请求参数的原始URI,注意也不包含主机名,如/envy/search.html?name=envy
$request_filename 当前请求的文件路径,由root或者alias指令与URI请求生成
$limit_rate 用于限制连接速率

举个例子,如请求http://127.0.0.1:8080/envy/think/hello.html,那么其中的部分信息如下:
全局变量名|内容|
-|:-:|
$host|127.0.0.1|
$server_port|8080|
$request_uri|/envy/think/hello.html|
$document_uri|/envy/think/hello.html|
$document_root|/var/www/html|
$request_filename|/var/www/html/envy/think/hello.html|

预定义变量

除了全局变量,Nginx还提供了很多预定义的变量,开发者也可以通过set来设置变量,下面是一些常用的预定义变量,可以看到这些和全局变量其实差不多:

预变量名 所表示的值
$args_name 请求中name参数的值
$args 所有请求参数
$query_string $args的别名
$content_length 请求头Content-Length的值
$content_type 请求头Content-Type的值
$host 如果当前有Host,那么为请求头Host的值;如果没有,那么该值等于匹配该请求的server_name的值
$remote_addr 客户端的IP地址
$request 客户端发起的完整请求,包括HTTP请求方法、URI、HTTP协议、头和请求体
$request_uri 客户端发起的完整请求的URI,注意包括参数
$scheme 当前请求的协议
$uri 当前请求的标准化URI

main模块

全局设置填写Nginx的全局配置,在此区域填写的内容会被应用到Nginx的全局,如修改Nginx默认的用户名(默认为nobody)可以在配置文件的开头加上user nginx,这样Nginx运行的用户就变成了nginx。

常用的全局配置项如下:
(1)worker_processes,表示Nginx开启的子进程数;
(2)error_log,表示定义全局错误日志文件,可选的值有debug、info、notice、warn、error、crit等;
(3)pid用于指定进程id的存储文件位置;
(4)worker_rlimit_nofile,用于指定Nginx进程最多可以打开的文件描述符数目。

举个例子,如下所示的配置信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定义Nginx运行的用户和用户组
user nginx nginx;

# Nginx进程数,一般建议为CPU的总核心数,或者设置为auto
worker_processes auto;

# 定义全局错误日志类型
error_log /var/log/nginx/error.log info;

# 进程文件
pid /var/run/nginx.pid;

# 一个Nginx进程最多可以打开的文件描述符数目,建议与ulimit -n的值保持一致
worker_rlimit_nofile 65536;

上面的例子只是为了示例,在实际使用工作中可以使用默认的配置,也就是不用作任何修改。

events模块

events模块用来指定Nginx的工作模式和单个进程的连接数上限。举个例子如下:

1
2
3
4
5
6
7
8
9
events {
# 参考事件模型,可选值有kqueue、rtsig、epoll、/dev/poll、select、poll
# epoll是linux2.6以上版本内核中的高性能网络I/O模型
# FreeBSD或者macOS可以使用kqueue模型
use epoll;

# 单个进程的最大连接数(默认是1024,最大连接数=连接数*进程数)
worker_connections 65535;
}

上述进程的最大连接数受Linux系统进程的最大打开文件数的限制,只有在执行操作系统命令ulimit -n 65536之后worker_connections的设置才会生效。

http模块

http部分是配置文件最核心的部分,它包括了绝大部分HTTP服务器相关属性的配置,如是否使用Keepalive,是否使用gzip进行压缩等,还包括server和upstream这些子模块,这些都是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
# 配置http服务器
http {
# 文件扩展名与文件类型映射表
include mime.types;
# 默认文件类型
default_type application/octet-stream;
# 默认编码
charset utf-8;
# 服务器名字的hash表大小
server_names_hash_bucket_size 128;
# 缓冲区代理缓冲用户端请求的最大字节数
client_body_buffer_size 128k;
# 允许客户端请求的最大单文件字节数
client_max_body_size 10m;
# 开启高效文件传输模式,启用之后Nginx会调用sendfile函数来输出文件
# I/O负载较大的应用,建议设置为off,以平衡磁盘与网络I/O处理速度,减少系统的负载
sendfile on;
#开启目录列表访问(默认关闭)
autoindex on;
# 防止网络阻塞
tcp_nopush on;
tcp_nodelay on;
# 长连接超时的时间,单位为秒
keepalive_timeout 120;

# gzip模块设置
# 开启gzip压缩输出
gzip on;
# 最小压缩文件的大小
gzip_min_length 1k;
# 压缩缓冲区
gzip_buffers 4 16k;
# 压缩版本
gzip_http_version 1.1;
# 压缩等级
gzip_comp_level 2;
# 压缩类型,默认已经包括text/html,因此下面的就可以不用写了
gzip_types text/plain application/x-javascript text/css application/xml;
# 下面的设置会在响应头上加个Vary:Accept-Encoding,可以让前端的缓存服务器经过gzip压缩的页面
gzip_vary on;
# 在开启限制IP连接数的时候需要使用下面的配置
limit_zone crawler $binary_remote_addr 10m;

upstream peoject_name {
......
}
server {
......
}
}

http模块的设置非常庞杂,这里只是列举一小部分配置。

server模块

server模块是http的子模块,它可以定义一个虚拟主机,基本配置如下所示:

1
2
3
4
5
6
7
8
9
10
server {
listen 2222;
server_name localhost 1.1.1.1 www.example.com;
root /nginx/www/path/;
index index.php index.html index.htm;
charset utf-8;
access_log usr/local/var/log/host.access.log main;
aerror_log usr/local/var/log/host.error.log error;
......
}

简单解释一下上述配置信息内容:
(1)server{}表示虚拟主机配置范围;
(2)listen用于指定虚拟主机的服务端口;
(3)server_name用于指定IP地址或者域名,在多个域名之间用空格分开;
(4)root表示在server这个虚拟主机内Web服务的根目录;
(5)index用于定义默认的首页地址;
(6)charset用于设置网页的默认编码格式;
(7)access_log用于指定虚拟主机访问日志的存放路径,后面接上日志的输出格式。

server模块的配置也很多,其中location模块也是server模块的子模块。

location模块

location模块是Nginx中可自定义程度最高的模块,它用于定位解析URL,通过使用正则匹配,用户可以通过location指令实现对网页的各种处理。

举个例子,下面这个反向代理中的location /就是用于匹配根目录:

1
2
3
4
location / {
root /nginx/www/path;
index index.php index.html index.htm;
}

upstream模块

upstream模块又称为负载均衡模块,下面通过一个简单的调度算法来认识这个模块:

1
2
3
4
5
6
7
upstream example.com {
fair;
server 192.168.73.1:80;
server 192.168.73.2:8080 down;
server 192.168.73.3:6666 max_fails=3 fail_timeout=20s max_conns=1000;
server 192.168.73.4:3333 backup;
}

在上面的例子中,通过使用upstream指令定义了一个名为example.com的负载均衡器,此处的名称可以随意指定,不一定是一个域名。其中的fair是一种负载均衡调度算法,后面的server表示真实服务器群组,后接真实服务器的IP地址。

请注意IP地址后面的down表示该server不参与负载均衡;backup表示预留的备份机器,只有当其他所有的非backup机器出现故障或者异常忙碌时,才会请求backup机器,所有这台机器的负载压力较小;max_fails表示允许请求失败的次数(默认为1次),当超过最大次数时返回proxy_next_upstream模块定义的错误。fail_timeout表示在经历max_fails次失败后暂停服务的时间。max_conns表示限制分配给后端服务器处理的最大连接数量,超过这个数量,将不会分配新的连接给它。

请注意,upstream模块中还有一个resolve选项,它需要配合http模块来使用,如下所示:

1
2
3
4
5
6
7
http {
resolver 192.168.73.100
upstream u {
......
server example.com resolve;
}
}

在http模块下配置resolver命令,指定域名解析服务为example.com域名,并且由192.168.73.100服务器来负责解析。关于upstream模块的常见配置,可以点击 这里 进行查阅。

下面用一张图来对nginx.conf主配置文件的内容进行总结:

完整配置文件示例

下面是一个较为完整的配置文件示例,内容如下所示:

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
user  nginx nginx;         # 运行用户和组,默认是nginx,可不进行设置
worker_processes 1; # Nginx 进程数,一般设置为CPU核数或者设置为auto
error_log /var/log/nginx/error.log warn; # 定义全局Nginx错误日志存放目录及类型
pid /var/run/nginx.pid; # Nginx服务启动时pid的存放位置
worker_rlimit_nofile 65536; # 一个Nginx进程最多可以打开的文件描述符数目,建议与ulimit -n的值保持一致

events {
use epoll; # 使用epoll这一I/O模型
worker_connections 65535; # 单个进程的最大连接数(默认是1024,最大连接数=连接数*进程数)
}

http { # 配置使用最频繁的部分,代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里设置
# 设置日志模式
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 /var/log/nginx/access.log main; # Nginx访问日志存放位置

sendfile on; # 开启高效传输模式
tcp_nopush on; # 减少网络报文段的数量
tcp_nodelay on;
keepalive_timeout 65; # 保持连接的时间,也称超时时间,单位秒
types_hash_max_size 2048;

include /etc/nginx/mime.types; # 文件扩展名与类型映射表
default_type application/octet-stream; # 默认文件类型

include /etc/nginx/conf.d/*.conf; # 加载子配置项

server {
listen 80; # 配置监听的端口
server_name localhost; # 配置的域名

location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认首页文件
deny 192.168.73.10; # 禁止访问的ip地址,可以为all
allow 192.168.73.18;# 允许访问的ip地址,可以为all
}

error_page 500 502 503 504 /50x.html; # 默认50x对应的访问页面
error_page 400 404 error.html; # 默认40x对应的访问页面
}
}

也就是说整个Nginx的核心配置文件的框架为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
worker_processes  1;
events {
worker_connections 1024;
}
http {
include mime.types;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
}
}

这样关于Nginx安装和配置文件的介绍就先学习到这。