Nginx服务器是如何处理请求的

版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原文出处,谢谢
原文出处: http://libiao.appspot.com/2010/01/nginx_processes_requests.html

Nginx是如何处理请求的?

 

1.       基于命名的虚拟服务器(Name-based virtual servers)

 

Nginx首先要确定由哪个服务器(server)来处理这个请求,如下面的简单的例子中,一共有3个虚拟主机,分别是:

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;

     

}

 

在上面的简单的配置中,nginx只需要简单的匹配下HTTP Request HeaderHost字段就可以决定由那个虚拟服务器来处理该请求了。如果Host字段没有匹配上所有的虚拟服务器的名称,那么nginx就将其转到默认的服务器上进行处理。一般情况下,第一个虚拟服务器为默认的服务器。如上面配置中的为nginx.org为默认的虚拟服务器。如果你不想让第一个服务器作为默认的服务器,那么可以对上述的服务器配置上进行更改,如将nginx.net作为默认的服务器,则只需要在listen 80后加default_server即可。

server {

      listen 80 default_server;

      server_name nginx.net www.nginx.net;

     

}

注意,default_server是在版本0.8.21才引入的,如果之前的版本的话,请使用default,而不是default_server

 

2.       怎么阻止一个没有定义服务器名称的请求

如在我的nginx里面没有定义这个虚拟服务器名称,但是有请求过来了,该怎么去阻止这个没有定义的服务器名称的请求呢?

只需要定义如下的server

server {

      listen 80 default_server;

      server_name _;

      return 444;

}

选择一个不存在的域名_作为服务器名称,然后返回nginx特有的(非标准化的)的code 444来终止该连接。

 

3.       综合了基于命名的和基于IP的虚拟服务器

让我们来看看更加复杂一点的nginx的配置, 其监听了不同的地址

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地址和端口来检查listen项。然后根据HTTP请求中的HOST来检查server_name值,如果没有找到对应的server_name,那么将请求转向给默认的服务器。如在192.168.1.1:80上接收到一个www.nginx.com的请求,但是因为在192.168.1.1:80上没有定义nginx.com这个服务器名称,因此,有nginx.org来处理该请求。

同时上面也说了,默认的服务器是跟绑定的端口绑定在一起的,因此,如果不同的绑定端口下可以设置不同的默认服务器的,如下面的例子:

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;

     

}

即在192.168.1.1:80下设置默认的虚拟服务器为nginx.net,而在192.168.1.2:80下默认的为nginx.com

 

4.       一个简单的PHP站点的配置

下面来看看如何给一个简单的PHP站点来设置location信息

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,如上面配置了3location,但是只有万不得已的情况下,才会将请求转到第一个location,即/这个目录下。然后按照配置文件中定义的正则表达式来批判locations,如果找到对应的表达式,则停止搜索,使用搜索到的location。如果没有找到对应的正则表达式的搜索结果,则使用最接近的文本匹配的location

需要注意的一点是,上面所有的location信息都是没有包含查询字符串(query string)的。因为查询字符串中包括了很多的显示方式,如:

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

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

同时也可能有其他的字符串在查询字符串中,如:

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

 

下面我们来看看上面的配置如何来处理一个请求

l         /logo.gif的请求。当用户请求/logo.gif过来的时候,首先被/这个location匹配上,然后由正则表达式\.(gif|png|jpg)$匹配上,因此使用后者。然后因为使用了root /data/www,那么/logo.gif请求就映射到文件/data/www/logo.gif上,并且将文件返回给用户。

l         /index.php的请求。首先/index.php也是被/匹配上,然后被正则表达式\.php$匹配上。因此需要选择后者,将请求转发到location\.php$上去。而在\.php$上其为一个fastcgi服务器,地址为localhost:9000fastcgi_param设置FastCGI的参数SCRIPT_FILENAME/data/www/index.php,然后FastCGI服务器执行该脚本。注意:$document_root等于上面root设定的值,即/data/www,而$fastcgi_script_name为请求的URI,即/index.php

l         /about.html的请求,因为该请求只是匹配上/这一项,因此,由location /来直接接受该请求,即将文件映射到/data/www/about.html,然后将结果返回给用户。

l         /的请求。上述的三个location中,/的请求是最复杂的。如果一个请求只是匹配上/这一项,那么就由location /来处理该请求。Index指令就是告诉该location,如果在设定的root下(如上面为/data/www)下有index下的文件,即index.html或者index.php存在的话,则在内部需要做一次重定向。即如果在/data/www下有index.php,则重定向给/index.php,参考上面的/index.php的请求来处理。

 

备注: location的语法

location [=|~|~*|^~] /uri {}

其中~是区分大小写的正则表达式

~*为不区分大小写的正则表达式

= 为了提高效率,实行严格匹配,如果找到,停止搜索,执行该location的内容

^~ 是如果匹配上路径之后,不测试正则表达式了,停止搜索

猜你喜欢

转载自kingoal.iteye.com/blog/561023