Nginx 是如何处理每一个请求的

        基于名字的虚拟主机
        Nginx 首先会决定哪个服务器应该处理这次请求。我们先以一个简单的配置看起,这里三个虚拟主机都监听到端口 *:80:
  1. server {  
  2.     listen      80;  
  3.     server_name example.org www.example.org;  
  4.     ...  
  5. }  
  6.   
  7. server {  
  8.     listen      80;  
  9.     server_name example.net www.example.net;  
  10.     ...  
  11. }  
  12.   
  13. server {  
  14.     listen      80;  
  15.     server_name example.com www.example.com;  
  16.     ...  
  17. }  

        在这一配置中,Nginx 仅仅根据请求头中的 "Host" 属性来决定将把当前请求路由到哪台服务器。如果该属性的值没有匹配到任意一台主机名,或者当前请求压根就没有包含这一属性,那么 Nginx 会将当前请求路由到这一端口的默认服务器。在上面的配置中,默认服务器是第一个 - 这是 Nginx 的标准默认行为。当然,也可以在 listen 指令中使用 default_server 参数来显式指定默认服务器:
  1. server {  
  2.     listen      80 default_server;  
  3.     server_name example.net www.example.net;  
  4.     ...  
  5. }  

        default_server 参数自 0.8.21 版本起开始生效。在早期版本中应该使用 default 参数。
        如何防止处理没有定义主机名的请求

        如果不允许头中没有 "Host" 属性的请求,可以定义 server 以丢弃这些请求:

  1. server {  
  2.     listen      80;  
  3.     server_name "";  
  4.     return      444;  
  5. }  

        这里,server 名被设置为空串,这将匹配没有  “Host” 头的请求,之后一个特殊的非标准的 HTTP 码 444 会在关闭连接的同时返回。

       自版本 0.8.48 起,这是 server 名的默认设置,因此可以忽略 server_name "" 的写法。在早期版本中,机器的主机名会被用作默认的 server 名。

        基于名字和基于 IP 的混合的虚拟主机
        我们继续看一下复杂一些的配置,这里虚拟主机监听不同地址:
  1. server {  
  2.     listen      192.168.1.1:80;  
  3.     server_name example.org www.example.org;  
  4.     ...  
  5. }  
  6.   
  7. server {  
  8.     listen      192.168.1.1:80;  
  9.     server_name example.net www.example.net;  
  10.     ...  
  11. }  
  12.   
  13. server {  
  14.     listen      192.168.1.2:80;  
  15.     server_name example.com www.example.com;  
  16.     ...  
  17. }  

        在这一配置中,Nginx 会首先检测当前请求的 IP 地址和端口号是否匹配 server 块的 listen 指令。然后,Nginx 继续检测当前请求的 "Host" 属性是否匹配 server 块的 server_name 入口。如果服务器名没有找到,当前请求会被默认服务器处理。例如,一个端口 192.168.1.1:80 接收到的关于 www.example.com 的请求会被默认的 192.168.1.1:80 端口服务器处理,比如,第一台服务器,因为没有找到这一端口定义的 www.example.com。
        上面说明过,默认服务器参数是监听端口的一个属性,可以针对不同端口定义不同的默认服务器:
  1. server {  
  2.     listen      192.168.1.1:80;  
  3.     server_name example.org www.example.org;  
  4.     ...  
  5. }  
  6.   
  7. server {  
  8.     listen      192.168.1.1:80 default_server;  
  9.     server_name example.net www.example.net;  
  10.     ...  
  11. }  
  12.   
  13. server {  
  14.     listen      192.168.1.2:80 default_server;  
  15.     server_name example.com www.example.com;  
  16.     ...  
  17. }  

        一个简单地 PHP 站点配置
        我们看一下 Nginx 是如何为一个典型而又简单的 PHP 站点的请求选择定位的:
  1. server {  
  2.     listen      80;  
  3.     server_name example.org www.example.org;  
  4.     root        /data/www;  
  5.   
  6.     location / {  
  7.         index   index.html index.php;  
  8.     }  
  9.   
  10.     location ~* \.(gif|jpg|png)$ {  
  11.         expires 30d;  
  12.     }  
  13.   
  14.     location ~ \.php$ {  
  15.         fastcgi_pass  localhost:9000;  
  16.         fastcgi_param SCRIPT_FILENAME  
  17.                       $document_root$fastcgi_script_name;  
  18.         include       fastcgi_params;  
  19.     }  
  20. }  

        Nginx 首先会找出最匹配前缀的位置,而不会考虑其出现顺序。在上面的配置中,唯一匹配前缀 location 的是 “/”,因为其可以匹配任何请求,它将被用作最后一个选择。然后 Nginx 会检查配置文件中一一列出的正则表达式。第一个匹配的表达式会停止查找并使用这一 location。如果没有任何正则表达式匹配这一请求,Nginx 会使用前面找到的最准确的前缀表达式 location。
        注意所有 location 匹配测试只使用请求的 URI 部分,而不使用参数部分。这是因为请求串中的参数可以以多种方式给出,例如:
  1. /index.php?user=john&page=1  
  2. /index.php?page=1&user=john  

        此外,一些人会使用以下请求串添加任何东西:
  1. /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 处理,这一请求会被传递给一个监听到 localhost:9000 的 FastCGI 服务器。fastcgi_param 指令设置 FastCGI 参数 SCRIPT_FILENAME 为 “/data/www/index.php”,FastCGI 将执行该文件。$document_root 变量等同于 root 指令的值,$fastcgi_script_name 变量等同于请求 URI,比如,“/index.php”。
  • 一个 “/about.html” 的请求会仅仅被 location “/” 匹配,因此,它将被这一 location 处理。使用指令 “root /data/www”,这一请求会被映射到 /data/www/about.html 文件,这一文件会被发送给客户端。
  • 处理一个 “/” 的请求有些复杂。它只会被前缀 location “/” 匹配,因此,它将由这一 location 处理。然后 index 指令会根据 “root /data/www” 指令检测 index 文件的存在。如果 /data/www/index.html 文件不存在,并且 /data/www/index.php 文件存在,然后这一指令会进行一个内部重定向到 “/index.php”,然后 Nginx 会再次寻找 location 对其进行匹配,就像这一请求时被一个客户端请求的一样。正如我们上面看到的,这一重定向请求将会最终被 FastCGI 服务器处理。
原文链接: http://nginx.org/en/docs/http/request_processing.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值