《Nginx官方文档》- Nginx如何处理请求

基于域名的虚拟服务器

Nginx会决定使用哪一个服务器接收请求。下面让我们看一个简单的配置示例,3台虚拟服务器都监听着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字段决定请求应该由哪一台服务器处理,如果Host字段的值没有相匹配的服务器或者请求中没有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;
}

上述配置中,server_name设置为空字符串,将匹配没有携带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地址以及端口,然后使用server_name去测试Host字段如果请求匹配了Ip地址以及端口。如果域名没有找到,请求将由默认服务器处理。举个例子,在192.168.1.1:80端口收到了对于www.example.com的请求,因为没有为该端口定义www.example.com的server_name,请求将由192.168.1.1:80的默认服务器处理,即配置中的第一台服务器。

如之前所述,默认服务器是监听端口的属性之一,并且可以为不同的监听端口匹配不同的默认服务器。

简单php站点的配置

接下来了解nginx如何处理简单php站点的请求,访问到请求所选择的location。

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前缀,并非根据配置中所定义的顺序。在上述配置中,"/"是最通用的,能够匹配任何请求,会被作为最后的手段使用。
然后nginx会按顺序使用配置中的location的正则表达式匹配地址。当匹配成功时,nginx会停止查找并且使用该location。如果请求没有和任何正则表达式匹配成功,那么nginx会使用之前查找到的最明确的location前缀。
值得注意的是,所有类型的location配置只会和请求的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)$”匹配,因此它将由后一个location处理。使用指令“root/data/www”将请求映射到文件/data/www/logo.gif,并将文件发送到客户端。
  • 请求”/index.php”首先由前缀”/”匹配,然后由正则表达式”/.(php)$”匹配。因此它将由后一个location处理,并且被转发到监听着location:9000端口的FastCGI服务器。fastcgi_param指令将FastCGI变量SCRIPT_FILENAME设置为”/data/www/index.php”,然后FastCGI执行该文件。变量$document_root变量等于root指令的值,变量$fastcgi_script_name等于请求的URI,即”/index.php”。
  • 请求”/about.html”只由前缀”/”匹配,因此将由该location处理。使用指令”root /data/www”将请求映射到文件/data/www/about.html,然后发送到客户端。
  • 处理请求”/”比较复杂。它只匹配了前缀”/”,因此由该location处理。然后index指令根据设置的变量以及”root /data/www”指令检查index文件是否存在。如果/data/www/index.html不存在,/data/www/index.php存在,会内部重定向到”index.php”,然后nginx再次使用这个地址搜索合适的location。正如我们之前所看到的,重定向的请求最终会被FastCGI服务器处理。

 

 Igor Sysoev写作
Brian Mercer修改

kailuncen 翻译

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/98139.html

(0)
上一篇 2021年8月20日 22:10
下一篇 2021年8月20日 22:10

相关推荐

发表回复

登录后才能评论