zoukankan      html  css  js  c++  java
  • Nginx是如何处理Request的?

    nginx是如何匹配过来的请求,然后做处理的呢?这个匹配的过程可以分为两步:
    1.选择server
    2.选择location 
     
    选择server
    仅仅匹配server name
    加入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仅仅匹配server_name指令。根据Request请求头的"Host"参数,去匹配server_name的指令参数,从而决定路由到哪个虚拟服务器。如果HOST 请求头参数找不到对应的server,或者压根没有这个请求头,那么nginx将会选择默认的——往往是第一个,这里是 server_name example.org www.example.org;   但是你也可以直接指定:
    server {
        listen      80 default_server;
        server_name example.net www.example.net;
        ...
    }
    在listen指令的后面,使用default_server参数就指定了默认的server。注意,这里指令参数default_server是放在指令listen后面,不是server_name后面,是指定一个具体的端口,不是指定一个虚拟机名称,后面会说明原因。
    如果请求头Header没有HOST参数,在0.8.48之后的版本,此请求会被丢弃。在之前的版本中,你可以用下面的指令来完成丢弃的功能:
    server {
        listen      80;
        server_name "";
        return      444;
    }
    指令server_name 的参数设为空数组将匹配不带Host请求头的请求。
     
    同时匹配server name和IP
    来看看同时带有IP和server name的server的配置情况:
    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;
        ...
    }
    在这种情况下,Ngxin首先根据请求的IP和Port匹配listen指令,然后再根据请求的Host头匹配server_name 指令。比如本机的ip是192.168.1.1,那么所有过来的请求都不会到192.168.1.2上去。如果Host没有匹配上,再用默认的server来处理。
    例如: 发往192.168.1.1:80端口的www.example.com请求,只会从前面两个server中去找对应的server_name,发现没有匹配上,那么采用默认的(第一个)server。
    我看来看看在多个IP的配置文件下,如何指定默认的server:
    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;
        ...
    }
    所以,server是针对某个IP,某个端口的,并不是针对某个域名,因此default_server也是针对某个IP,某个端口的,是listen的属性而不是server_name 的属性。
     
    选择 location 
    location指令都是针对请求的uri部分进行匹配,不是整个url,也不包含任何请求参数,比如:
    /index.php
    /user/index/get
     
    Nginx的locating指令可以分为两种,即"prefix location"和"regular expression location",即“前缀location”和“正则location”。
    前缀location形如下面:
    location / {
           ....
    }
    location /path/to {
            .....
     }
    location /index.php {
           .....
     }
     
    正则location location后面需要匹配正则表达式,比如:
      location ~* .(gif|jpg|png)$ {
            expires 30d;
       }
     
    以一个PHP网站的配置为例,看看Nginx如果选择location来处理请求的。
    server {
        listen      80;
        server_name example.org www.example.org;
        root        /data/www;
     
        location / {
            index  index.html index.php;
        }
     
        location /comment {
            rewrite /comment/(.*) /$1 break;
        }
     
        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中进行匹配,而且首先搜寻匹配的最为"精确"的那一项:比如请求/comment,即匹配location /comment 和location / 但是location /comment 更为“精确”因此被匹配上。location / 因为是匹配所有的请求所以被“最后考虑”。这一步匹配是无关前缀location的罗列顺序的。
    接着,nginx继续匹配正则location,这一步跟正则location的顺序就有关系了。nginx是依次匹配,第一个匹配的到location时。nginx会终止匹配,然后用这个location来处理请求。如果正则location部分没有匹配到任何一项,则采用上一步前缀location匹配到的来处理请求。
    在匹配到location,处理Request时,还需要加上root指令,即root   /data/www;
     
    举例说明下:
    "/logo.gif"——首先被前缀location的location /匹配上了,然后也被正则location的location ~* .(gif|jpg|png)$ 匹配上了,因此会被后面的location处理。此外,在处理请求是还要加上root   /data/www ,最为请求就被定为到了 /data/www/logo.gif,最后次文件会被发送到浏览器
     
    "/index.php"——同样首先被前缀location的location /匹配上,但后面正则location也匹配上了location ~ .php$,因此由后者来处理:交给运行在localhost:9000的FASTCGI程序来处理,
    fastcgi_param 指令用来设定FASTCGI的参数SCRIPT_FILENAME,$document_root和$fastcgi_script_name是nginx参数,分别为root指令参数(/data/www)和URI(/index.php)
     
    "/about.html"——仅仅能被location /匹配,因此便由它处理,最后请求定位到/data/www/about.html
     
    "/"——这种情况稍微复杂点。它仅能被前缀location"location /"匹配上,因此它将被这个location处理。然后location中的指令index将被执行,nginx会依次尝试index文件(俗称入口文件)是否存在,在此例中就是/data/www/index.html /data/www/index.php,如果前者不存在就继续往后找。此例中,/data/www/index.html不存在因此由/data/www/index.php处理。然后nginx会做个内部跳转到/index.php,然后,就处理好像一个从浏览器反过来的全新请求一样,重新搜寻location,就像前面分析的一样,最终交由FASTCGI程序来处理。
     
     
     
  • 相关阅读:
    Dotnet Core 跨平台GUI 开发实践
    微软的wasm 和 rust的wasm 方案对比
    全栈程序员的新玩具Rust(六)第一个WASM程序
    全栈程序员的新玩具Rust(五)第一个http服务器
    全栈程序员的新玩具Rust(四)第一个图形程序
    全栈程序员的新玩具Rust(三)板条箱
    全栈程序员的新玩具Rust(二)基本代码入门
    mac 上使用 zip 版的mysql
    磁盘 I/O 优化
    Netty WebSocket 开发
  • 原文地址:https://www.cnblogs.com/minirice/p/8304886.html
Copyright © 2011-2022 走看看