在Nginx配置文件中,每一条指令配置都必须以分号结束,请不要忘记。
用户组配置
用于配置运行Nginx服务器用户(组)的指令是user,其语法格式为:
user user [group];
- user,指定可以运行Nginx服务器的用户。
- group,可选项,指定可以运行Nginx服务器的用户组。
只有被设置的用户或者用户组成员才有权限启动Nginx进程,如果是其他用户(test_user)尝试启用Nginx进程,将会报错:
nginx: [emerg] getpwnam("test_user") failed (2: No such file or directory) in
/Nginx/conf/nginx.conf:2
可以从错误信息中看到,Nginx无法运行的原因是查找test_user失败,引起错误的原因是nginx.conf的第二行内容,即配置Nginx服务器用户(组)的内容。 如果希望所有用户都可以启动Nginx进程,有两种办法:一是将此指令行注释掉:
#user [user] [group];
或者将用户(和用户组)设置为nobody:
user nobody nobody;
这也是user指令的默认配置。user指令只能在全局块中配置。
配置worker-process数
worker process是Nginx服务器实现并发处理服务的关键所在。从理论上来说,worker process的值越大,可以支持的并发处理量也越多,但实际上它还要受到来自软件本身、操作系统本身资源和能力、硬件设备(如CPU和磁盘驱动器)等的制约。后面会用专门的章节来讨论Nginx服务器的高级配置。
配置允许生成的worker process数的指令是worker_processes,其语法格式为:
worker_processes number | auto;
- number,指定Nginx进程最多可以产生的worker process数。
- auto,设置此值,Nginx进程将自动检测。
在默认的配置文件中,number=1。启动Nginx服务器以后,使用以下命令可以看到Nginx服务器除了主进程master process ../sbin/nginx之外,还生成了一个worker process:
#ps ax | grep nginx
8579 ? Ss 0:00 nginx: master process ../sbin/nginx
8580 ? S 0:00 nginx: worker process
如果将number改为3,重新运行Nginx进程,再次使用以上命令,则可以看到此时的Nginx服务器除了主进程master process ../sbin/nginx之外,已经生成了三个worker process:
#ps ax | grep nginx
8626 ? Ss 0:00 nginx: master process ../sbin/nginx
8627 ? S 0:00 nginx: worker process
8628 ? S 0:00 nginx: worker process
8629 ? S 0:00 nginx: worker process
此指令只能在全局块中设置。
配置最大连接数
指令worker_connections主要用来设置允许每一个worker process同时开启的最大连接数。其语法结构为:
worker_connections number;
此指令的默认设置为512。
MIME-Type配置
在常用的浏览器中,可以显示的内容有HTML、XML、GIF及Flash等种类繁多的文本、媒体等资源,浏览器为区分这些资源,需要使用MIME Type。换言之,MIME Type是网络资源的媒体类型。Nginx服务器作为Web服务器,必须能够识别前端请求的资源类型。
在默认的Nginx配置文件中,我们看到在http全局块中有以下两行配置:
include mime.types;
default_type application/octet-stream;
第二行中使用指令default_type配置了用于处理前端请求的MIME类型,其语法结构为:
default_type mime-type;
其中,mime-type为types块中定义的MIME-type,如果不加此指令,默认值为text/plain。此指令还可以在http块、server块或者location块中进行配置。
PID存放路径
Nginx进程作为系统的守护进程运行,我们需要在某文件中保存当前运行程序的主进程号。Nginx支持对它的存放路径进行自定义配置,指令是pid,其语法格式为:
pid file ;
其中,file指定存放路径和文件名称。
配置文件默认将此文件存放在Nginx安装目录logs下,名字为nginx.pid。path可以是绝对路径,也可以是以Nginx安装目录为根目录的相对路径。比如要把nginx.pid放置到Nginx安装目录sbin下,文件名为web_nginx,则可以使用以下配置:
pid sbin/web_nginx
错误日志路径配置
在全局块、http块和server块中都可以对Nginx服务器的日志进行相关配置。这里首先介绍全局块下日志的存放配置,后两种情况的配置基本相同,只是作用域不同。使用的指令是error_log,其语法结构是:
error_log file| stderr [debug | info | notice | warn | error | crit | alert | emerg];
从语法结构可以看到,Nginx服务器的日志支持输出到某一固定的文件file或者输出到标准错误输出stderr;日志的级别是可选项,由低到高分为debug(需要在编译时使用--with-debug开启debug开关)、info、notice、warn、error、crit、alert、emerg等。需要注意的是,设置某一级别后,比这一级别高的日志也会被记录。比如设置warn级别后,级别为warn以及error、crit、alert和emerg的日志都会被记录下来。
下面我们先看一个配置的实例,这也是Nginx默认的日志存放和级别设置:
error_log logs/error.log error;
配置access_log
在全局块中,我们介绍过errer_log指令,其用于配置Nginx进程运行时的日志存放和级别,此处所指的日志与常规的不同,它是指记录Nginx服务器提供服务过程应答前端请求的日志,我们将其称为服务日志以示区分。
Nginx服务器支持对服务日志的格式、大小、输出等进行配置,需要使用两个指令,分别是access_log和log_format指令。
access_log指令的语法结构为:
access_log path [format [buffer=size]];
- path,配置服务日志的文件存放的路径和名称。
- format,可选项,自定义服务日志的格式字符串,也可以通过“格式串的名称”使用log_format指令定义好的格式。“格式串的名称”在log_format指令中定义。
- size,配置临时存放日志的内存缓存区大小。
此指令可以在http块、server块或者location块中进行设置。默认的配置为:
access_log logs/access.log combined;
其中,combined为log_format指令默认定义的日志格式字符串的名称。 如果要取消记录服务日志的功能,则使用:
access_log off;
和access_log联合使用的另一个指令是log_format,它专门用于定义服务日志的格式,并且可以为格式字符串定义一个名字,以便access_log指令可以直接调用。其语法格式为:
log_format name string …;
- name,格式字符串的名字,默认的名字为combined。
- string,服务日志的格式字符串。在定义过程中,可以使用Nginx配置预设的一些变量获取相关内容,变量的名称使用双引号括起来,string整体使用单引号括起来。
我们来看一个示例以加深理解:
log_format exampleLog '$remote_addr - [$time_local] $request '
'$status $body_bytes_sent $http_referer '
'$http_user_agent';
这条配置定义了服务日志文件的名称为exampleLog。笔者对其测试的结果,输出了如下日志片段:
192.168.1.102 - [31/Oct/2019:20:41:39 +0800] "GET / HTTP/1.1" 200 151 "-" "Mozilla/5.0
(compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"
192.168.1.102 - [31/Oct/2019:20:41:39 +0800] "GET /favicon.ico HTTP/1.1" 404 570 "-"
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"
简单分析一下第二条日志,$remote_addr
获取到用户机的IP地址为192.168.1.102,$time_local
获取到本地时间为31/Oct/2019:20:41:39 +0800,$request
获取到请求为GET /favicon.ico HTTP/1.1
,$status
获取到请求状态为404(未找到,这是笔者将请求的网页暂时移除造成的),$body_bytes_sent
获取到请求体的大小为570B,$http_referer
未获取到任何内容,$http_user_agent
获取到用户使用Mozilla浏览器。
sendfile 传输文件配置
在Apache、lighttd等Web服务器配置中,都有和sendfile相关的配置,这里主要学习一下配置sendfile传输方式的相关指令sendfile和sendfile_max_chunk以及它们的语法结构:
sendfile on | off;
用于开启或者关闭使用sendfile()传输文件,默认值为off,可以在http块、server块或者location块中进行配置。
sendfile_max_chunk size;
其中,size值如果大于0,Nginx进程的每个worker process每次调用sendfile()传输的数据量最大不能超过这个值;如果设置为0,则无限制。默认值为0。此指令可以在http块、server块或location块中配置。
下面是第二个指令的配置示例:
sendfile_max_chunk 128k;
配置连接超时时间
与用户建立会话连接后,Nginx服务器可以保持这些连接打开一段时间,指令keepalive_timeout就是用来设置此时间的,其语法结构是:
keepalive_timeout timeout [header_timeout];
- timeout,服务器端对连接的保持时间。默认值为75s。
- header_timeout,可选项,在应答报文头部的Keep-Alive域设置超时时间:“Keep-Alive:timeout= header_timeout”。报文中的这个指令可以被Mozilla或者Konqueror识别。
此指令还可以出现在server块和location块中,如下是一个配置示例:
keepalive_timeout 120s 100s;
其含义是,在服务器端保持连接的时间设置为120 s,发给用户端的应答报文头部中Keep-Alive域的超时时间设置为100 s。
单连接请求数上限
Nginx服务器端和用户端建立会话连接后,用户端通过此连接发送请求。指令keepalive_requests用于限制用户通过某一连接向Nginx服务器发送请求的次数。其语法结构为:
keepalive_requests number;
此指令还可以出现在server块和location块中,默认设置为100。
监听端口配置
配置监听使用指令listen,其配置方法主要有三种,我们先分别介绍三种配置的语法结构,然后统一介绍涉及的相关变量和标识符。第一种配置监听的IP地址,语法结构为:
listen address[:port] [default_server] [setfib=number] [backlog=number] [rcvbuf=size]
[sndbuf=size] [deferred]
[accept_filter=filter] [bind] [ssl];
第二种配置监听端口,其语法结构是:
listen port[default_server][setfib=number][backlog=number][rcvbuf=size][sndbuf=
size] [accept_filter=filter]
[deferred] [bind] [ipv6only=on|off] [ssl];
第三种配置UNIX Domain Socket(一种在原有Socket框架上发展起来的IPC机制,用于在单个主机上执行客户/服务器通信,这不是本书的重点,请读者自行参阅相关书籍),其语法结构为:
listen unix:path [default_server] [backlog=number] [rcvbuf=size] [sndbuf=size]
[accept_filter=filter] [deferred]
[bind] [ssl];
- address,IP地址,如果是IPv6的地址,需要使用中括号“[]”括起来,比如[fe80::1]等。
- port,端口号,如果只定义了IP地址没有定义端口号,就使用80端口。
- path,socket文件路径,如/var/run/nginx.sock等。
- default_server,标识符,将此虚拟主机设置为address:port的默认主机。
基于server_name的主机配置
这里的“主机”,就是指此server块对外提供的虚拟主机。设置了主机的名称并配置好DNS,用户就可以使用这个名称向此虚拟主机发送请求了。配置主机名称的指令为server_name,其语法结构为:
server_name name …;
对于name 来说,可以只有一个名称,也可以由多个名称并列,之间用空格隔开。每个名字就是一个域名,由两段或者三段组成,之间由点号“.”隔开。下面是一个简单的示例:
server_name myserver.com www.myserver.com;
在该例中,此虚拟主机的名称设置为myserver.com或www. myserver.com。Nginx服务器规定,第一个名称作为此虚拟主机的主要名称。
在name 中可以使用通配符“*”,但通配符只能用在由三段字符串组成的名称的首段或尾段,或者由两段字符串组成的名称的尾段,如:
server_name *.myserver.com www.myserver.*;
在name中还可以使用正则表达式,并使用波浪号“~”作为正则表达式字符串的开始标记,如:
server_name ~^www\d+\.myserver\.com$;
正则表达式的主机配置
理解正则表达式的捕获功能,大家看一个示例。虚拟主机的名称设置如下:
server_name ~^www\.(.+)\.com$;
当请求通过www.myserver.com
到达Nginx服务器端时,其将会被上面的正则表达式配置成功,其中的“myserver”将会被捕获,并记录到$1
中。在本server块的下文配置中,当需要“myserver”时,就可以使用$1
代替“myserver”了。
由于server_name
指令支持使用通配符和正则表达式两种配置名称的方式,因此在包含有多个虚拟主机的配置文件中,可能会出现一个名称被多个虚拟主机的server_name
匹配成功。那么,来自这个名称的请求到底要交给哪个虚拟主机处理呢?Nginx服务器做出如下规定:
对于匹配方式不同的,按照以下的优先级选择虚拟主机,排在前面的优先处理请求。
- 准确匹配server_name
- 通配符在开始时匹配server_name成功
- 通配符在结尾时匹配server_name成功
- 正则表达式匹配server_name成功
在以上四种匹配方式中,如果server_name被处于同一优先级的匹配方式多次匹配成功,则首次匹配成功的虚拟主机处理请求。
基于ip地址的主机配置
参考以下配置信息:
http
{
…
server #第一台虚拟主机
{
listen: 80;
server_name: 192.168.1.31;
…
}
server #第二台虚拟主机
{
listen: 80;
server_name: 192.168.1.32;
…
}
…
}
经过以上的配置,来自192.168.1.31的前端请求将由第一台虚拟主机接收和处理,来自192.168.1.32的前端请求将由第二台虚拟主机接收和处理。
基于ip的访问权限配置
Nginx配置通过两种途径支持基本访问权限的控制,其中一种是由HTTP标准模块ngx_http_access_module支持的,其通过IP来判断客户端是否拥有对Nginx的访问权限,这里有两个指令需要我们学习。
allow指令
用于设置允许访问Nginx的客户端IP,语法结构为:
allow address | CIDR | all;
- address,允许访问的客户端的IP,不支持同时设置多个。如果有多个IP需要设置,需要重复使用allow指令。
- CIDR,允许访问的客户端的CIDR地址,例如202.80.18.23/25,前面是32位IP地址,后面“/25”代表该IP地址中前25位是网络部分,其余位代表主机部分。
- all,代表允许所有客户端访问。
从Nginx 0.8.22版本以后,该命令也支持IPv6地址,比如:
allow 2620:100:e000::8001;
deny指令
作用刚好和allow指令相反,它用于设置禁止访问Nginx的客户端IP,语法结构为:
deny address | CIDR | all;
- address,禁止访问的客户端的IP,不支持同时设置多个。如果有多个IP需要设置,需要重复使用deny指令。
- CIDR,禁止访问的客户端的CIDR地址。
- all,代表禁止所有客户端访问。
这两个指令可以在http块、server块或者location块中配置。在使用这两个指令时,要注意设置为all的用法。请看下面的例子:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
deny all;
}
在上面的配置示例中我们首先配置禁止192.168.1.1
访问Nginx,然后配置允许192.168.1.0/24
访问Nginx,最后又使用all配置禁止所有IP的访问。那么,192.168.1.0/24
客户端到底可不可以访问呢?是可以的。Nginx配置在解析的过程中,遇到deny指令或者allow指令是按照顺序对当前客户端的连接进行访问权限检查的。如果遇到匹配的配置时,则停止继续向下搜索相关配置。因此,当192.168.1.0/24
客户端访问时,Nginx在第3行解析配置发现允许该客户端访问,就不会继续向下解析第4行了。
基于密码配置Nginx的访问权限
Nginx还支持基于HTTP Basic Authentication协议的认证。该协议是一种HTTP性质的认证办法,需要识别用户名和密码,认证失败的客户端不拥有访问Nginx服务器的权限。该功能由HTTP标准模块ngx_http_auth_basic_module支持,这里有两个指令需要学习。
- auth_basic指令
用于开启或者关闭该认证功能,语法结构为:
auth_basic string | off;
-
string,开启该认证功能,并配置验证时的指示信息。
-
off,关闭该认证功能。
-
auth_basic_user_file指令
用于设置包含用户名和密码信息的文件路径,语法结构为:
auth_basic_user_file file;
其中,file为密码文件的绝对路径。
这里的密码文件支持明文或者密码加密后的文件。明文的格式如下所示:
name1:password1
name2:password2:comment
name3:password3
加密密码可以使用crypt()函数进行密码加密的格式,在Linux平台上可以使用htpasswd命令生成。在PHP和Perl等语言中,也提供crypt()函数。使用htpasswd命令的一个示例为:
# htpasswd -c -d /nginx/conf/pass_file username
运行后输入密码即可。
location配置
在Nginx的官方文档中定义的location的语法结构为:
location [ = | ~ | ~* | ^~ ] uri { ... }
其中,uri变量是待匹配的请求字符串,可以是不含正则表达的字符串,如 /myserver.php
等;也可以是包含有正则表达的字符串,如 .php$
(表示以.php结尾的URL)等。为了下文叙述方便,我们约定,不含正则表达的uri称为“标准uri”,使用正则表达式的uri称为“正则uri”。
其中方括号里的部分,是可选项,用来改变请求字符串与 uri 的匹配方式。在介绍四种标识的含义之前,我们需要先了解不添加此选项时,Nginx服务器是如何在server块中搜索并使用location块的uri和请求字符串匹配的。
在不添加此选项时,Nginx服务器首先在server块的多个location块中搜索是否有标准uri和请求字符串匹配,如果有多个可以匹配,就记录匹配度最高的一个。然后,服务器再用location块中的正则uri和请求字符串匹配,当第一个正则uri匹配成功,结束搜索,并使用这个location块处理此请求;如果正则匹配全部失败,就使用刚才记录的匹配度最高的location块处理此请求。
了解了上面的内容,就可以解释可选项中各个标识的含义了:
- “=”,用于标准uri前,要求请求字符串与uri严格匹配。如果已经匹配成功,就停止继续向下搜索并立即处理此请求。
- “~”,用于表示uri包含正则表达式,并且区分大小写。
- “~*”,用于表示uri包含正则表达式,并且不区分大小写。
如果uri包含正则表达式,就必须要使用“~”或者“~*”标识。
“^~”,用于标准uri前,要求Nginx服务器找到标识uri和请求字符串匹配度最高的location后,立即使用此location处理请求,而不再使用location块中的正则uri和请求字符串做匹配。
我们知道,在浏览器传送URI时对一部分字符进行URL编码,比如空格被编码为“%20”,问号被编码为“%3f”等。“~”有一个特点是,它对uri中的这些符号将会进行编码处理。比如,如果location块收到的URI为“/html/%20/data”,则当Nginx服务器搜索到配置为“~ /html/ /data”的location时,可以匹配成功。
location root配置
Web服务器接收到网络请求之后,首先要在服务器端指定目录中寻找请求资源。在Nginx服务器中,指令root就是用来配置这个根目录的,其语法结构为:
root path;
其中,path为Nginx服务器接收到请求以后查找资源的根目录路径。path变量中可以包含Nginx服务器预设的大多数变量,只有$document_root
和$realpath_root
不可以使用。
此指令可以在http块、server块或者location块中配置。由于使用Nginx服务器多数情况下要配置多个location块对不同的请求分别做出处理,因此该指令通常在location块中进行设置。
这个指令的一个示例为:
location /data/
{
root /locationtest1;
}
当location块接收到“/data/index.htm”
的请求时,将在/locationtest1/data/
目录下找到index.htm
响应请求。
location alias配置
在location块中,除了使用root指令指明请求处理根目录,还可以使用alias指令改变location接收到的URI的请求路径,其语法结构为:
alias path;
其中,path即为修改后的根路径。同样,此变量中也可以包含除了realpath_root之外的其他Nginx服务器预设变量。
这个指令的作用有点不好理解,我们来看一个示例:
location ~ ^/data/(.+\.(htm|htm))$
{
alias /locationtest1/other/$1;
}
当此location块接收到/data/index.htm
的请求时,匹配成功,之后根据alias指令的配置,Nginx服务器将到/locationtest1/other
目录下找到index.htm
并响应请求。可以看到,通过alias指令的配置,根路径已经从/data
更改为/locationtest1/other
了。
index首页配置
指令index用于设置网站的默认首页,它一般可以有两个作用:一是,用户在发出请求访问网站时,请求地址可以不写首页名称;二是,可以对一个请求,根据其请求内容而设置不同的首页。该指令的语法结构为:
index file ...;
其中,file变量可以包括多个文件名,其间使用空格分隔,也可以包含其他变量。此变量默认为“index.html”。
看一个示例:
location ~ ^/data/(.+)/web/ $
{
index index.$1.html index.my1.html index.html;
}
当location块接收到/data/locationtest/web/
时,匹配成功,它首先将预置变量$1置为locationtest
,然后在/data/locationtest/web/
路径下按照index的配置次序依次寻找index.locationtest.html
页、index.my1.html
页和index.html
页,首先找到哪个页面,就使用哪个页面响应请求。
error_page错误页面配置
如果用户端尝试查看网页时遇到问题,服务器会将HTTP错误从网站发送到Web浏览器。如果无法显示网页,Web浏览器会显示网站发送的实际错误网页或Web浏览器内置的友好错误消息。Nginx服务器支持自定义错误网页的显示内容。可以通过这一功能在网站发生错误时为用户提供人性化的错误显示页面。
一般来说,HTTP 2XX代表请求正常完成,HTTP 3XX代表网站重定向,HTTP 4XX代表客户端出现错误,HTT 5XX代表服务器端出现错误。
Nginx服务器设置网站错误页面的指令为error_page,语法结构为:
error_page code ... [=[response]] uri
- code,要处理的HTTP错误代码,常见的在表2.2中已经列出。
- response,可选项,将code指定的错误代码转化为新的错误代码response。
- uri,错误页面的路径或者网站地址。如果设置为路径,则是以Nginx服务器安装路径下的html目录为根路径的相对路径;如果设置为网址,则Nginx服务器会直接访问该网址获取错误页面,并返回给用户端。
看几个error_page指令的示例:
error_page 404 /404.html
设置Nginx服务器使用“Nginx安装路径/html/404.html”页面响应404错误(“无法找到网页”错误)。再如:
error_page 403 http://somewebsite.com/forbidden.html;
设置Nginx服务器使用http://somewebsite.com/forbidden.html页面响应403错误(“拒绝显示网页”错误)。再如:
error_page 410 =301 /empty.gif
设置Nginx服务器产生410的HTTP消息时,使用“Nginx安装路径/html/empty.gif”返回给用户端301消息(“已移动”消息)。
在前面对error_page指令的分析中我们看到,变量uri实际上是一个相对于Nginx服务器安装路径的相对路径。那么,如果不想将错误页面放到Nginx服务器的安装路径下管理,该怎么做呢?
其实这个很简单,只需要另外使用一个location指令定向错误页面到新的路径下面了就可以了。比如对于上面的第一个示例,我们希望Nginx服务器使用“/myserver/errorpages/404.html”页面响应404错误,那么在设置完:
error_page 404 /404.html
之后,我们再添加这样一个location块:
location /404.html
{
root /myserver/errorpages/
}
首先捕获“/404.html”请求,然后将请求定向到新的路径下面即可。 errer_page指令可以在http块、server块和location块中配置。
include指令
在一些情况下,我们可能需要将其他的Nginx配置或者第三方模块的配置引用到当前的主配置文件中。Nginx提供了include指令来完成配置文件的引入,其语法结构为:
include file;
其中,file是要引入的配置文件,它支持相对路径。
配置是否同时接收多个网络连接
每个Nginx服务器的worker process都有能力同时接收多个新到达的网络连接,但是这需要在配置文件中进行设置,其指令为multi_accept,语法结构为:
multi_accept on | off;
此指令默认为关闭(off)状态,即每个worker process一次只能接收一个新到达的网络连接。此指令只能在events块中进行配置。
配置事件驱动模型
Nginx服务器提供了多种事件驱动模型来处理网络消息。配置文件中为我们提供了相关的指令来强制Nginx服务器选择哪种事件驱动模型进行消息处理,指令为use,语法结构为:
use method;
其中,method可选择的内容有:select、poll、kqueue、epoll、rtsig、/dev/poll以及eventport。
配置网络连接序列化
在《UNIX网络编程》里提到过一个叫“惊群”的问题(Thundering herd problem),大致意思是,当某一时刻只有一个网络连接到来时,多个睡眠进程会被同时叫醒,但只有一个进程可获得连接。如果每次唤醒的进程数目太多,会影响一部分系统性能。在Nginx服务器的多进程下,就有可能出现这样的问题。
为了解决这样的问题,Nginx配置中包含了这样一条指令accept_mutex,当其设置为开启的时候,将会对多个Nginx进程接收连接进行序列化,防止多个进程对连接的争抢。其语法结构为:
accept_mutex on | off;
此指令默认为开启(on)状态,其只能在events块中进行配置
网友评论