nginx-2 如何处理一个请求

nginx接收一个请求后,首先由listen和server_name指令匹配server模块,再匹配server模块里的location,最后就是location里的具体处理(可以是代理转发请求或者直接返回静态内容...)

基于名称的虚拟服务器

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判断使用那个服务器的依据是request头部中的HostHost 匹配到哪个server_name就使用哪个服务器。如果都不匹配,则使用默认的服务器。在未显示指定默认服务器的情况下,比如上面的这个例子,nginx认为第一个server为默认服务器。如需显示指定,如下。

# 0.8.21 版本以前使用的是default
server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}

注意:default_server 是监听端口的一个属性。

如何处理不含Host头部的请求

server {
    listen      80;
    # 使用空字符串匹配未定义的Host
    server_name "";
    # 返回一个特殊状态码,并关闭连接
    return      444;
}

注意:0.8.48版本以后,""是server_name的默认值,所以此处可以省略server_name "";在更早的版本,server_name的默认值为主机的hostname。

基于名称和IP的混合虚拟服务器

前提知识:一台主机可以有多个IP(多网卡),一个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首先匹配监听IP地址和端口,匹配成功之后,再匹配相应的server_name,这个通过之后就选择使用该server处理请求,否则使用默认的server。正如前面所说,default_server 是监听端口的一个属性,所以不同的默认服务器应该有且只有一个定义在不同的IP:端口,如下。

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网站配置例子

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按照配置文件中列出的顺序检查正则表达式给出的位置。第一个匹配表达式停止搜索,nginx将使用此位置。如果没有与请求匹配的正则表达式,那么nginx使用前面找到的最具体的前缀位置。

注意,所有类型的位置只测试匹配(test)请求行的URI部分,不包含参数(query_string)。这是因为查询字符串中的参数可以通过多种方式给出,例如:

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

此外,请求查询字符串中的内容是变化的;

/index.php?page=1&something+else&user=john

所以location只有匹配uri的功能,没有匹配query_string的功能。

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

  • /log.gif
    首先匹配位置/,接着匹配~* \.(gif|jpg|png)$,因此,由后者处理。使用指令root /data/www,请求被映射到/data/www/logo.gif,该文件被发送回客户端。
  • /index.php
    首先匹配位置/,接着匹配~ \.php$,因此由后者处理。请求配传递到监听在localhost:9000的FastCGI服务器。fastcgi_param指令设置了参数SCRIPT_FILENAME/data/www/xxx.xxx(xxx.xxx = fastcgi_script_name),然后FastCGI服务器执行了该文件。变量document_root等同于root指令的参数,变量fastcgi_script_name等同于请求的uri,比如/index.php
  • /about.html
    只匹配位置/,因此由其处理,请求被映射到/data/www/about.html,该文件被发送回客户端。
  • /
    处理/比较复杂。它只匹配位置/,因此由其处理。index指令根据它的参数和root /data/www依次检测index文件是否存在。如果/data/www/index.html不存在,/data/www/index.php存在,index指令会内部重定向到/index.php,nginx再次搜索这些location,就好像请求是由客户机发送的一样。如上所述,重定向的请求将会被FastCGI服务器处理。

你可能感兴趣的:(nginx-2 如何处理一个请求)