Nginx如何处理一个请求

author: Igor Sysoev
翻译:赵培龙
原文地址

1.基于名字的虚拟服务器

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,nginx会主动去检查http请求中的host字段,根据host字段的值来判断该把这个请求交给哪一个虚拟服务器来处理。如果没有找到匹配的虚拟服务器名,那么nginx会把这个请求交给默认的虚拟服务器,在上面的配置中,默认的服务器是第一个。当然我们也可以显示的指出(使用default_server)哪一个服务器是默认服务器,

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

在0.8.21的版本之后使用default_server,之前的版本都是使用的defalut

2.如何处理一个没有带host值的http请求

如果请求头里没有host的值,那么我们在配置中可以这样子定义:

server {
    listen      80;
    server_name "";
    return      444;
}
直接返回444
在0.8.48的版本之后,配置中默认的有这种处理方式,但之前的版本都是匹配上的默认服务器
# 基于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和端口,然后才是匹配头里面的host字段,都没有匹配到的情况下就会送给默认的服务器。

配置一个简单的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;
    }
}

location后面的那些字符串是一个正则表达式,用来匹配URI的,比如location后面的”/“就是来匹配任何请求的,nginx是最长匹配原则来匹配的。

注意到所有的location都没有包含URI的参数,这个是由于URI的参数的写法太多了,举个例子

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

现在我们来看看具体的例子


  1. 一个带有”/logo.gif”首先被 location “/“匹配,然后被”.(gif|jpg|png)$”匹配,但是这个是被后面的那个处理,由于root的值是/data/www所以访问的文件的地址是/data/www/logo.gif,nginx会把这个文件发给客户端
  2. 一个带有”/index.php”依然首先被”/“匹配到,然后被”.(php)$”匹配,这个还是被后面那个location处理。这个请求会传递给fastCGI服务器localhost:9000,fastcgi_param这个配置项是设置FastCGI参数”SCRPT_FILENAME”为”data/www/index.php”,FastCGI服务器会执行这个php脚本,变量$document_root就是root配置项的值,变量$fastcgi_script_name的值就等于请求的URI,这里是”/index.php”
  3. 一个带有”/about.html”依然会最先被”/“匹配,但是由于没有其他的匹配他,所以就直接被”/“处理了,由于root的值是/data/www,所以nginx会找到/data/www/about.html发给客户端。
  4. 处理一个请求”/“更加复杂,这个请求首先被location “/“匹配上,然后又被其处理
    ,这个location里面有一个配置项叫做index,这个配置项测试在/data/www(root配置项的值)文件夹下是否有inde.html文件,如果有,则发给客户端,如果没有,若是存在/data/www/index.phph,则重定向到”/index.php”,这个请求又会重新被定向到处理php的location中进行处理,流程和普通的带有”/*.php”一样。