您的位置:首页 > 运维架构 > Nginx

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

2016-10-14 13:19 204 查看
        基于名字的虚拟主机

        Nginx 首先会决定哪个服务器应该处理这次请求。我们先以一个简单的配置看起,这里三个虚拟主机都监听到端口 *:80:

[plain]
view plain
copy
print?





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 参数来显式指定默认服务器:

[plain]
view plain
copy
print?





server {  
    listen      80 default_server;  
    server_name example.net www.example.net;  
    ...  
}  

        default_server 参数自 0.8.21 版本起开始生效。在早期版本中应该使用 default 参数。

        如何防止处理没有定义主机名的请求
        如果不允许头中没有 "Host" 属性的请求,可以定义 server 以丢弃这些请求:

[plain]
view plain
copy
print?





server {  
    listen      80;  
    server_name "";  
    return      444;  
}  

        这里,server 名被设置为空串,这将匹配没有 “Host” 头的请求,之后一个特殊的非标准的 HTTP 码 444 会在关闭连接的同时返回。
       自版本 0.8.48 起,这是 server 名的默认设置,因此可以忽略 server_name "" 的写法。在早期版本中,机器的主机名会被用作默认的 server 名。

        基于名字和基于 IP 的混合的虚拟主机

        我们继续看一下复杂一些的配置,这里虚拟主机监听不同地址:

[plain]
view plain
copy
print?





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 指令。然后,Nginx 继续检测当前请求的 "Host" 属性是否匹配 server 块的 server_name 入口。如果服务器名没有找到,当前请求会被默认服务器处理。例如,一个端口 192.168.1.1:80 接收到的关于 www.example.com 的请求会被默认的 192.168.1.1:80 端口服务器处理,比如,第一台服务器,因为没有找到这一端口定义的 www.example.com。

        上面说明过,默认服务器参数是监听端口的一个属性,可以针对不同端口定义不同的默认服务器:

[plain]
view plain
copy
print?





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 站点的请求选择定位的:

[plain]
view plain
copy
print?





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。

        注意所有 location 匹配测试只使用请求的 URI 部分,而不使用参数部分。这是因为请求串中的参数可以以多种方式给出,例如:

[plain]
view plain
copy
print?





/index.php?user=john&page=1  
/index.php?page=1&user=john  

        此外,一些人会使用以下请求串添加任何东西:

[plain]
view plain
copy
print?





/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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nginx