nginx如何处理一个请求
基于命名的虚拟服务器
Nginx首先决定哪个服务器应该处理一个请求。让我们从一个简单的配置开始,三个虚拟服务器都监听端口*:80
:
server {
listen 80;
server_name example.org www.example.org;
...
}
server {
listen 80;
server_name example.net www.example.net;
...
}
server {
listen 80;
server_name example.com www.example.com;
...
}
在这个配置中,nginx只测试请求的报头字段“Host”,以确定请求应该路由到哪个服务器。如果它的值不匹配任何服务器名,或者请求根本不包含这个报头字段,那么nginx将把请求路由到这个端口的默认服务器。在上面的配置中,默认的服务器是第一个——这是nginx的标准默认行为。它也可以通过listen指令中的default_server参数显式设置哪个服务器应该是默认的:
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
default_server参数从0.8.21版本开始就可用了。在早期版本中,应该使用default参数。
请注意,默认服务器是侦听端口的属性,而不是服务器名的属性。稍后再详细介绍。
如何防止处理未定义服务器名的请求
如果没有“Host”报头字段的请求不被允许,可以定义一个只删除请求的服务器:
server {
listen 80;
server_name "";
return 444;
}
在这里,服务器名被设置为一个空字符串,将匹配没有“Host”报头字段的请求,并且返回一个特殊的nginx的非标准码444来关闭连接。
从版本0.8.48开始,这是服务器名的默认设置,所以可以省略server_name ""。在早期版本中,机器的主机名被用作默认的服务器名
基于名称和ip的混合虚拟服务器
让我们看看一个更复杂的配置,一些虚拟服务器监听不同的地址:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
...
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
...
}
在这个配置中,nginx首先根据server块的listen指令来测试请求的IP地址和端口。然后,它根据匹配IP地址和端口的server块的server_name条目测试请求的“Host”报头字段。如果没有找到服务器名,则该请求将由默认服务器处理。
例如,在192.168.1.1:80端口上接收到的www.example.com请求将由192.168.1.1:80端口的默认服务器处理,也就是第一个server,因为没有为这个端口定义www.example.com。
如前所述,默认服务器是监听端口的一个属性,不同的端口可以定义不同的默认服务器:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.1.1:80 default_server;
server_name example.net www.example.net;
...
}
server {
listen 192.168.1.2:80 default_server;
server_name example.com www.example.com;
...
}
一个简单的PHP站点配置
现在让我们来看看nginx是如何为典型的简单PHP站点选择一个位置来处理请求的:
server {
listen 80;
server_name example.org www.example.org;
root /data/www;
location / {
index index.html index.php;
}
location ~* \.(gif|jpg|png)$ {
expires 30d;
}
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Nginx首先搜索由字面值字符串给出的最特定的前缀位置,而不考虑列出的顺序。在上面的配置中,唯一的前缀位置是“/”,因为它匹配任何请求,所以它将被用作最后的手段。然后nginx按照配置文件中列出的顺序检查正则表达式给出的位置。第一个匹配的表达式终止搜索,nginx将使用这个位置。如果没有正则表达式匹配一个请求,那么nginx使用之前找到的最特定的前缀位置。
请注意,所有类型的位置只测试请求行的URI部分,不带参数。这样做是因为查询字符串中的参数可能以几种方式给出,例如:
/index.php?user=john&page=1
/index.php?page=1&user=john
此外,任何人都可以请求查询字符串中的任何内容:
/index.php?page=1&something+else&user=john
现在让我们看看在上面的配置中请求是如何被处理的:
- 请求“/logo.gif”首先由前缀位置“/”匹配,然后由正则表达式“.(gif|jpg|png)$”匹配,因此,它由后一个位置处理。使用指令" root /data/www ",请求被映射到文件/data/www/logo.gif,然后文件被发送到客户端。
- 请求" /index.php "也首先由前缀位置" / "匹配,然后由正则表达式" .(php) "匹配。因此,它由后一个位置处理,请求被传递到一个FastCGI服务器,这个服务器监听在localhost:9000。fastcgi_param指令将FastCGI参数SCRIPT_FILENAME设置为“/data/www/index.php”,然后FastCGI服务器执行该文件。变量document_root等于根指令的值,变量$fastcgi_script_name等于请求的URI,即“/index.php”。
- 请求“/about.html”只与前缀位置“/”匹配,因此,它在这个位置处理。使用指令“root /data/www”,请求被映射到文件/data/www/about.html,文件被发送到客户端。
- 处理一个“/”的请求更为复杂。它只由前缀位置“/”匹配,因此,它由这个位置处理。然后index指令根据它的参数和“root /data/www”指令测试索引文件是否存在。如果文件/data/www/index.html不存在,并且文件/data/www/index.php存在,那么指令会内部重定向到" /index.php ",然后nginx会再次搜索这个位置,就像这个请求是由客户端发送的一样。正如我们之前看到的,重定向请求最终将由FastCGI服务器处理。
作者:Igor Sysoev
编辑:Brian Mercer
翻译:xinlan
注:本文是对官网文档的翻译
欢迎来到testingpai.com!
注册 关于