文章目录
1. 根目录和索引文件
root指令明确了用于查找文件的根目录。为了得到请求文件的路径,NGINX将请求URI追加到root指令指定的路径后。指令可以放在任何级别的http{},server{}或location{}上下文中。在下面的示例中,root指令被虚拟服务器定义,它应用到所有没有root指令的location块中。
server {
root /www/data;
location / {
}
location /images/ {
}
location ~ \.(mp3|mp4) {
root /www/media;
}
}
在这里,NGINX在文件系统 /www/data/images/ 目录中搜索以 /images/ 开头的URI。但是,如果URI以.mp3或.mp4扩展名结尾,则NGINX会在/www/media/目录中搜索文件,因为它在匹配的location块中定义。
如果请求以斜杠结尾,NGINX会将其视为对目录的请求,并尝试在目录中查找索引文件。index指令定义索引文件的名称(默认值为index.html)。继续该示例,如果请求URI为 /images/some/path/,则NGINX传送文件/www/data/images/some/path/index.html(如果存在)。如果文件不存在,则默认情况下NGINX返回HTTP代码404。要将NGINX配置为返回自动生成的目录列表,请在autoindex指令中添加on参数。
location /images/ {
autoindex on;
}
您可以在index指令中列出多个文件名。NGINX按照指定的顺序搜索文件,并返回找到的第一个文件。
location / {
index index.$geo.html index.htm index.html;
}
这里使用的$geo变量是通过geo指令设置的自定义变量。变量的值取决于客户端的IP地址。
为了得到索引文件,NGINX检查其存在,并将索引文件的名称添加到基本URI后面,以便内部重定向获取URI。内部重定向将导致对location的新搜索,并可能最终到达另一个location,如以下示例所示:
location / {
root /data;
index index.html index.php;
}
location ~ \.php {
fastcgi_pass localhost:8000;
#...
}
这里,如果URI的请求是 /path/ ,而且 /data/path/index.html 不存在但是 /data/path/index.php 存在,/path/index.php 内部重定向映射到第二个location。结果,该请求被代理。
2. 尝试几个选项
try_files指令被用于检测指定的文件或目录是否存在。如果存在,NGINX进行内部重定向;反之,返回状态码。例如,要检查是否存在与请求URI相对应的文件,请使用try_files指令和$uri变量,如下所示:
server {
root /www/data;
location /images/ {
try_files $uri /images/default.gif;
}
}
文件由URI的格式确定,该URI使用在当前location或虚拟服务器的上下文中设置的root或alias指令进行处理。在这种情况下,如果不存在与原始URI对应的文件,NGINX将内部重定向到由最后一个参数指定的URI,返回/www/data/images/default.gif。
最后一个参数也可以是状态代码(直接在等号后)或location名称。以下示例中,如果try_files指令的任何参数都无法解析到现有文件或目录,则将返回404错误。
location / {
try_files $uri $uri/ $uri.html =404;
}
在下一个示例中,如果原始URI或带有尾随斜杠的URI都无法解析到现有文件或目录中,则该请求将被重定向到指定的location,该location会将其传递给代理服务器。
location / {
try_files $uri $uri/ @backend;
}
location @backend {
proxy_pass http://backend.example.com;
}
3. 优化性能以提供内容
加载速度是提供任何内容的关键因素。对NGINX配置进行小的优化可能会提高生产率并帮助达到最佳性能。
3.1 启用 sendfile
默认情况下,NGINX自行处理文件传输,并在发送文件之前将文件复制到缓冲区中。启用sendfile指令可以消除将数据复制到缓冲区的步骤,并可以将数据从一个文件描述符直接复制到另一个文件描述符。另外,为防止一个快速连接完全占用工作进程,您可以使用sendfile_max_chunk指令限制单个sendfile()调用中传输的数据量(本例中为1M):
location /mp3 {
sendfile on;
sendfile_max_chunk 1m;
#...
}
3.2 启用 tcp_nopush
将tcp_nopush指令与sendfile on指令一起使用。这样一来,这使NGINX能够在 sendfile() 获得数据块后立即在一个数据包中发送HTTP响应头。
location /mp3 {
sendfile on;
tcp_nopush on;
#...
}
3.3 启用 tcp_nodelay
tcp_nodelay指令允许覆盖Nagle算法,该算法最初旨在解决速度较慢的网络中的小数据包问题。该算法将多个小数据包合并为一个较大的数据包,并以200ms的延迟发送数据包。如今,在处理大型静态文件时,无论数据包大小如何,都可以立即发送数据。延迟还会影响在线应用程序(SSH,在线游戏,在线交易等)。默认情况下,tcp_nodelay指令设置为on,意味着Nagle算法被禁用。仅对需要保持的连接使用此指令:
location /mp3 {
tcp_nodelay on;
keepalive_timeout 65;
#...
}
3.4 优化积压队列
重要的因素之一是NGINX可以处理传入连接的速度。一般规则是,建立连接后,将其放入listen套接字的监听队列中。在正常负载下,队列很小或根本没有队列。但是在高负载下,队列会急剧增长,从而导致性能不均匀,连接断开和延迟增加。
3.4.1 显示监听队列
要显示当前监听队列,请运行以下命令(FreeBSD系统下):
netstat -Lan
输出可能类似于以下内容,该结果表明在80端口上的侦听队列中, 在已配置的最大128队列连接数中,存在10个不可接受的连接。这种情况是正常的。
Current listen queue sizes (qlen/incqlen/maxqlen)
Listen Local Address
0/0/128 *.12345
10/0/128 *.80
0/0/128 *.8080
相反,在以下命令中,不可接受的连接数(192)超过了128的限制。当网站流量很大时,这是很常见的。为了获得最佳性能,您需要增加操作系统和NGINX配置中的最大连接数。
Current listen queue sizes (qlen/incqlen/maxqlen)
Listen Local Address
0/0/128 *.12345
192/0/128 *.80
0/0/128 *.8080
3.4.2 调整操作系统
将net.core.somaxconn内核参数的值从其默认值(128)增加到足以应付大流量的数值。在此示例中,将其增加到4096。
- 对于FreeBSD,运行命令:
sudo sysctl kern.ipc.somaxconn=4096
- 对于Linux:
- 运行命令:
sudo sysctl -w net.core.somaxconn=4096
- 使用文本编辑器将以下行添加到/etc/sysctl.conf:
net.core.somaxconn = 4096
3.4.5 调优NGINX
如果将somaxconn内核参数设置为大于的值512,请修改NGINX listen指令的backlog参数来匹配:
server {
listen 80 backlog=4096;
# ...
}
参考文档
https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/