Appearance
Nginx如何处理请求
提示
来自deepseek解释
Nginx如何处理一个请求
基于名称的虚拟服务器
Nginx首先需要决定哪个 server 块应该处理请求。让我们从一个简单的配置开始,其中三个虚拟服务器都监听在 *:80 端口上:
nginx
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”字段来决定将请求路由到哪个服务器。如果“Host”字段的值与任何 server_name 都不匹配,或者请求中根本没有这个头字段,Nginx会将请求路由到该端口的默认服务器。在上面的配置中,默认服务器是第一个,这是Nginx的标准默认行为。
也可以通过 listen 指令的 default_server 参数来显式指定哪个服务器是默认的:
nginx
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}请注意,默认服务器是监听端口的属性,而不是服务器名称的属性。
如何禁止处理未定义服务器名称的请求
如果不允许没有“Host”头字段的请求,可以定义一个直接丢弃请求的服务器:
nginx
server {
listen 80;
server_name "";
return 444;
}在这里,服务器名称被设置为空字符串,它将匹配没有“Host”头字段的请求,并返回Nginx的非标准状态码444,这会关闭连接。
混合基于名称和基于IP的虚拟服务器
现在来看一个更复杂的配置,其中一些虚拟服务器监听在不同的地址上:
nginx
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首先根据请求的IP地址和端口,与 server 块的 listen 指令进行匹配。然后,它再根据请求的“Host”头字段,与匹配上IP地址和端口的 server 块中的 server_name 进行匹配。如果找不到服务器名称,请求将由默认服务器处理。
如前所述,默认服务器是监听端口的属性,可以为不同的端口定义不同的默认服务器:
nginx
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站点配置
现在来看一个典型的、简单的PHP站点配置中,Nginx如何选择 location 来处理请求:
nginx
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首先搜索由字面字符串给出的、最具体的前缀 location,无论它们在配置文件中的列出顺序如何。在上面的配置中,唯一的前缀 location 是 /,因为它能匹配任何请求,所以被用作后备选项。
然后,Nginx按照配置文件中的顺序检查正则表达式 location。第一个匹配的正则表达式会停止搜索,Nginx将使用这个 location。如果没有正则表达式匹配,则Nginx使用之前找到的最具体的前缀 location。
请注意,所有类型的 location 都只测试请求行中的URI部分,而不包括参数。
请求示例分析
请求
/logo.gif首先匹配前缀location/,然后匹配正则表达式\.(gif|jpg|png)$。因此,它由后者处理。通过root /data/www指令,请求被映射到文件/data/www/logo.gif,并发送给客户端。请求
/index.php同样,首先匹配前缀location/,然后匹配正则表达式\.(php)$。因此,它由后者处理,请求被传递到监听在localhost:9000的FastCGI服务器。fastcgi_param指令将FastCGI参数SCRIPT_FILENAME设置为/data/www/index.php,FastCGI服务器将执行该文件。请求
/about.html仅匹配前缀location/,因此由该location处理。通过root /data/www指令,请求被映射到文件/data/www/about.html并发送给客户端。请求
/处理这个请求更为复杂。它仅匹配前缀location/,因此由该location处理。然后,index指令会根据其参数和root /data/www指令,检查索引文件是否存在。如果文件/data/www/index.html不存在,而/data/www/index.php存在,则该指令会执行一个内部重定向到/index.php。随后,Nginx会像客户端重新发起请求一样,再次搜索location。正如我们之前看到的,这个重定向后的请求最终将由FastCGI服务器处理。