nginx处理web请求分析

Nginx是什么?Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为“engine X”, 是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器.Nginx是由俄罗斯人 Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的,它已经在该站点运行超过两年半了。Igor Sysoev在建立的项目时,使用基于BSD许可。

笔者的VPS使用的是nginx服务器,以前配置都是从网上拷贝过来的,一直一知半解,正好手头有VPS可以玩,趁这个机会认真学习下nginx的配置.下面的文章是讲nginx如何处理web请求(web request)过程的。

一、基于域名的虚拟服务器

nginx首先确定使用哪一个server域来处理请求,下面的例子中有3个虚拟服务器监听*:80端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
server_name nginx.org www.nginx.org;
...
}
  
server {
listen 80;
server_name nginx.net www.nginx.net;
...
}
  
server {
listen 80;
server_name nginx.com www.nginx.com;
...
}

在上面的配置中,nignx根据HTTP请求“Host”的值,确定具体哪一个server接收web请求。如果“Host”不存在或者Host的值无法匹配任何sever中的$host_name,nginx就会把web请求送到默认的server中。如果没有定义default_server,默认将请求传递给第一个server。

1
2
3
4
5
server {
    listen       80  default_server;
    server_name  nginx.net  www.nginx.net;
    ...
}

参数“default_server” 是0.8.21后版本新增的内容. 此前的版本用“default”代替。
上面是针对web请求中包含“Host”值的情况,如果这个值不存在,那么可以使用下面的方法。

二、如何处理无server_name的请求?

1
2
3
4
5
6
server {
    listen       80  default_server;
    server_name  _;
    return       444;
   #所用"Host"为空的请求返回444响应。
}

三、处理基于IP和域名的虚拟主机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
    listen       192.168.1.1:80;
    server_name  nginx.org  www.nginx.org;
    ...
}
  
server {
    listen       192.168.1.1:80;
    server_name  nginx.net  www.nginx.net;
    ...
}
  
server {
    listen       192.168.1.2:80;
    server_name  nginx.com  www.nginx.com;
    ...
}

上面的配置中,nginx首先匹配IP地址和端口,然后在确定响应IP下的server_name,如果没有找到任何匹配的server_name,ngixn将请求传递给默认server。例如,当nginx收到来自 192.168.1.1:80 端口的请求www.nginx.com,
上例中没有定义默认server,那么这个请求将被传递到第一个server中。
nginx可以为不同的IP地址和端口定义多个默认server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
    listen        192.168.1.1:80;
    server_name   nginx.org  www.nginx.org;
    ...
}
  
server {
    listen        192.168.1.1:80  default_server;
    server_name   nginx.net  www.nginx.net;
    ...
}
  
server {
    listen        192.168.1.2:80  default_server;
    server_name   nginx.com  www.nginx.com;
    ...
}

四、如何处理PHP请求

下面我们来看看nginx是如何确定web请求的location的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
    listen        80;
    server_name   nginx.org  www.nginx.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 / {…}。然后再依次包含匹配正则表达式的location,如果没有找到匹配的正则表达式,nginx会将请求重新定位到定位符”/”下。
个人理解:nginx会优先处理定位符"/"、"/images"这些location,其次才按顺序匹配包含正则的location。例如:"./logo.gif"的请求首先会匹配定位符"/",其次是通用表达式"\.(gif|jpg|png)$",因此它被第二个定位符所匹配.Nginx会使用指令"root /data/www"将请求映射到文件"/data/www/logo.gif",之后文件被返回给客户端。换言之,ngixn总是会把请求传递到最后一个匹配的location中。
需要注意到的是,ngixn处理的URI中不包含查询字符串(query string)部分,因为这些查询字符串的不确定因素太多,例如:

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

也可以这样写:

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

最后看一下上面的例子中,nignx是如何处理的:

  1. “./logo.gif”的请求首先会匹配定位符”/”,其次是通用表达式”\.(gif|jpg|png)$”,因此它被第二个定位符所匹配.Nginx会使用指令”root /data/www”将请求映射到文件”/data/www/logo.gif”,之后文件被返回给客户端
  2. “/index.php”的请求也一样,首先匹配定位符”/”,其次是通常表达式”\.(php)$”.因而它由后者处理,请求被传递给在localhost:9000监听的FastCGI服务.”fastcgi_param”指令将FastCGI的参数SCRIPT_FILENAME设置为”/data/www/index.php”,再由FastCGI服务器执行该文件.变量$document_root的值与”root”指令的值是相等的,变量$fastcgi_script_name的值等于所请求的url,如”/index.php”等等
  3. 带”/about.html”的请求只匹配定位符”/”,因此它将在这个定位符中得到处理,由”root /data/www”指令将请求映射到”/data/www/about.html”,最后文件才被返回给客户端.
  4. 处理”/”这样的请求就更复杂了,因为只匹配”/”定位符所以只能在其中处理.”index”指令会根据它的参数及”root /data/www”指令,测试该目录下是否有默认文件存在.例如,如果存在”/data/www/index.php”文件,请求会被内部重定向到”/index.php”,然后Nginx会据此再进行一次定位符搜索,看起来就像是新接收到一个请求命令.一般而言,被重定向的请求最后会由FastCGI服务处理.
此条目发表在web server分类目录,贴了标签。将固定链接加入收藏夹。