基于名称的虚拟服务器
nginx收到请求时第一步是决定由哪个服务器来处理。以一个配置了三个虚拟服务器的例子为例,三个虚拟服务器军监听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只对请求的“Host”头域检查,并根据其值决定将请求路由给哪个服务器。如果和任何一个服务器都不匹配,或者请求不包含一个“Host”头域,那么nginx会将请求路由给监听在该端口上的默认服务器。上述配置中,默认服务器为第一个,nginx默认第一项为默认服务器。通过default_server可以显示的指定默认服务器:
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
(注意:默认服务器属性在0.8.21以后的版本才有)
怎么样禁止处理携带未定义服务器名的请求
如果收到一个没有携带Host头域的请求,那么该请求应该不处理而直接抛弃掉。通过如下配置即可:
server {
listen 80;
server_name "";
return 444;
}
服务器名设置为空字符串,这样就可以配未携带Host头域的请求,然后返回一个nginx的非标准444响应并关闭连接。
混合基于名称和基于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和端口是否匹配请求中携带的IP和端口是否,然后再检查上一步各匹配项中的server_name是否存在匹配请求的Host头域的。如果不存在,那么请求将被路由给默认服务器处理。
例如,一个从192.168.1.1:80接收并发给www.example.com的请求将被监听在192.168.1.1:80的默认服务器处理,即上面配置中的第一个服务器,因为该端口上没有名为www.example.com的服务器。如上所述,默认服务器是一个监听端口的属性,那么不同的端口可以有不同的默认服务器:
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站点配置
现在,看看nginx怎样为选择一个location为典型、简单的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。在上述的配置中,唯一的前缀匹配location是”/”,因为它匹配任何请求,因此它是所有请求的最后选择。nginx检查配置文件中顺序列出的location中的正则表达式,遇到第一个匹配项(此处为全匹配而不是前缀匹配)时即停止然后使用该项。如果没有找到,nginx将使用此前找到的匹配前缀最明确的location。注意所有类型的locations(前缀、全部)只和请求的URI组成部分对比,而不包括参数。这是因为查询字符串中的参数可能以多种方式出现,如:
/index.php?user=john&page=1
/index.php?page=1&user=john
同时,任何人都可以再请求字符串中请求任何东西:
/index.php?page=1&something+else&user=john
现在,我们来看一下在以上配置下,请求将会被怎么处理:
1、请求”/logo.gif” 匹配前缀location “/”,其次匹配正则表达式”.(gif|jpg|png)$”.因此,该请求将被后面的location处理。因为”root /data/www”,该请求被影射到文件/data/www/logo.gif,该文件将被发送到客户端
2、请求”/index.php” 也匹配前缀location “/”,并且匹配正则表达式\.(php)$
根据规则,请求将被后者处理,被发送到监听在localhost:9000的一个FastCGI服务器。fastcgi_param指定设置FastCGI 参数SCRIPT_FILENAME 为/data/www/index.php
。FastCGI服务器将执行该文件。参数$document_root
的值为root指向的目录,$fastcgi_script_name
和请求中携带的URI相同如"/index.php"
3、请求”/about.html”之和前缀匹location”/”匹配,因此,它将被该location处理。根据配置”root /data/www”,该请求被映射到文件 /data/www/about.html,并且该文件将被发送到客户端
4、处理请求”/”相对而言更加复杂。它只和前缀location “/” 匹配,因此将被该location处理。”index”配置项根据配置”root /data/www” 检查index文件是否存在。若果文件/data/www/index.html不存在,而文件/data/www/index.php存在,那么该请求将被在nginx内部被重定向为index.php,然后nginx好像从客户端收到该请求一样重新搜索location。如前所述,该重定向请求将被FastCGI服务器处理。