nginx 如何处理一个请求 (翻译文档)

本贴最后更新于 984 天前,其中的信息可能已经东海扬尘

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

现在让我们看看在上面的配置中请求是如何被处理的:

作者:Igor Sysoev

编辑:Brian Mercer

翻译:xinlan

注:本文是对官网文档的翻译

回帖
请输入回帖内容 ...