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
头部中的Host
,Host
匹配到哪个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服务器处理。