本节介绍如何使用NGINX来提供静态内容服务,定义搜索路径以查找请求的文件的方法,以及如何设置索引文件。
在这个部分,我们主要涉及以下几个方面的内容:
- 根目录和索引文件
- 尝试几个选项
- 优化NGINX服务内容的速度
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/
目录中搜索.mp3
或.mp4
文件,因为它在匹配的location
块中定义。
如果请求以斜杠结尾,则NGINX将其视为对目录的请求,并尝试在目录中找到索引文件。index
指令定义索引文件的名称(默认值为index.html
)。继续示例,如果请求URI为/images/some/path/
,则NGINX会传递文件/www/data/images/some/path/index.html
(如果存在)。 如果不存在文件,NGINX默认返回HTTP代码404
(未找到)。 要配置NGINX以返回自动生成的目录列表,请将on
参数添加到autoindex
指令中:
location /images/ {
autoindex on;
}
可以在索引指令中列出多个文件名。 NGINX以指定的顺序搜索文件,并返回它找到的第一个文件。
location / {
index index.$geo.html index.html 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指令可用于检查指定的文件或目录是否存在并进行内部重定向,如果没有指定的文件或目录,则返回特定的状态代码。 例如,要检查与请求URI相对应的文件的存在,请使用try_files
指令和$uri
变量,如下所示:
server {
root /www/data;
location /images/ {
try_files $uri /images/default.gif;
}
}
该文件以URI的形式指定,它使用在当前位置或虚拟服务器的上下文中设置的 root
或 alias
伪指令进行处理。 在这种情况下,如果与原始URI相对应的文件不存在,则NGINX将内部重定向到最后一个参数中指定的URI,也就是返回/www/data/images/default.gif
。
最后一个参数也可以是一个状态代码(直接在前面的等号)或位置的名称。 在以下示例中,如果try_files
指令的任何参数都不会解析为现有文件或目录,则会返回404错误。
location / {
try_files $uri $uri/ $uri.html =404;
}
在下一个示例中,如果原始URI和带有附加尾部斜线的URI都不能解析为现有文件或目录,则将请求重定向到将其传递给代理服务器的命名位置(location
)。
location / {
try_files $uri $uri/ @backend;
}
location @backend {
proxy_pass http://backend.example.com;
}
3. 优化NGINX服务内容的速度
加载速度是服务任何内容的关键因素。 对您的NGINX配置进行小幅优化可能会提高生产力并帮助实现最佳性能。
启用sendfile
默认情况下,NGINX会自动处理文件传输,并在发送文件之前将其复制到缓冲区中。 启用sendfile指令将消除将数据复制到缓冲区中的步骤,并允许将数据从一个文件描述符直接复制到另一个文件描述符。 或者,为了防止一个快速连接完全占用工作进程,您可以通过定义sendfile_max_chunk指令来限制在单个sendfile()
调用中传输的数据量:
location /mp3 {
sendfile on;
sendfile_max_chunk 1m;
...
}
启用tcp_nopush
将tcp_nopush选项与sendfile
一起使用。 该选项将使NGINX能够通过sendfile
获取数据块之后,在一个数据包中发送HTTP响应头
location /mp3 {
sendfile on;
tcp_nopush on;
...
}
启用tcp_nodelay
tcp_nodelay选项可以覆盖Nagle的算法,最初是为了解决慢网络中的小数据包问题而设计的。 该算法将大量小数据包整合到较大的数据包中,并以200 ms
的延迟发送数据包。
如今,当服务大型静态文件时,无论数据包大小如何,都可以立即发送数据。 延迟也会影响在线应用程序(ssh,在线游戏,网上交易)。 默认情况下,tcp_nodelay
指令设置为on
,表示Nagle的算法被禁用。 该选项仅用于Keepalive
连接:
location /mp3 {
tcp_nodelay on;
keepalive_timeout 65;
...
}
优化积压队列
其中一个重要因素是NGINX可以处理传入连接的速度。 一般规则是建立连接时,将其放入监听套接字的“侦听”队列中。 在正常负载下,有一个低队列,或根本没有队列。 但是在高负载下,队列可能会急剧增长,这可能会导致性能不均衡,连接丢失和延迟。
测量侦听队列
让我们来查看当前的侦听队列。 运行命令:
netstat -Lan
命令输出可能如下所示:
Current listen queue sizes (qlen/incqlen/maxqlen)
Listen Local Address
0/0/128 *.12345
10/0/128 *.80
0/0/128 *.8080
命令输出显示端口80
的监听队列中有10
个不接受的连接,而连接限制为128
个连接,这种情况是正常的。
但是,命令输出可能如下所示:
Current listen queue sizes (qlen/incqlen/maxqlen)
Listen Local Address
0/0/128 *.12345
192/0/128 *.80
0/0/128 *.8080
命令输出显示超过128个连接限制的192个不可接受的连接。 当网站的流量很大时,这是很常见的。 为了达到最佳性能,您需要增加NGINX在操作系统和NGINX配置中排队等待接收的最大连接数。
调整操作系统
将net.core.somaxconn
键的值从其默认值(128
)增加到足够高的值以能够处理高突发流量:
对于FreeBSD,运行命令:
sudo sysctl kern.ipc.somaxconn=4096
对于FreeBSD,运行命令:
sudo sysctl -w net.core.somaxconn=4096
打开文件:/etc/sysctl.conf
,将下面一行添加到文件并保存文件:
net.core.somaxconn = 4096
调整NGINX
如果将somaxconn
键设置为大于512
的值,请更改NGINX listen指令的backlog
参数以匹配:
server {
listen 80 backlog 4096;
# The rest of server configuration
}