基于域名的虚拟服务器
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根据请求头信息中的Host字段决定请求应该由哪一台服务器处理,如果Host字段的值没有相匹配的服务器或者请求中没有Host字段,那么Nginx会将请求路由至这个端口的默认服务器。在上文的配置中,默认的服务器是第一台,这是Nginx的默认策略。默认服务器是可以显式配置的,在listen指令使用default_server参数即可指定服务器为该端口的默认服务器。
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
default_server参数自从0.8.21版本开始启用,在更早期的版本中,使用default参数替代。
值得注意的是,默认服务器是属于监听端口的,而不是服务器名称。更多关于这点的信息之后会提及。
如何避免处理未定义域名的请求
如果不允许出现未携带Host字段的请求,希望服务器直接将其丢弃,可以使用如下配置:
server {
listen 80;
server_name "";
return 444;
}
上述配置中,server_name设置为空字符串,将匹配没有携带Host信息的请求,并且会返回nginx的非标准返回码444关闭连接。
自从0.8.48版本后,这是server_name的默认配置,所以””可以被省略了。在更早期的版本中,机器的域名被用作默认服务器名
基于域名和基于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首先使用server块的listen指令的配置去测试请求的ip地址以及端口,然后使用server_name去测试Host字段如果请求匹配了Ip地址以及端口。如果域名没有找到,请求将由默认服务器处理。举个例子,在192.168.1.1:80端口收到了对于www.example.com的请求,因为没有为该端口定义www.example.com的server_name,请求将由192.168.1.1:80的默认服务器处理,即配置中的第一台服务器。
如之前所述,默认服务器是监听端口的属性之一,并且可以为不同的监听端口匹配不同的默认服务器。
简单php站点的配置
接下来了解nginx如何处理简单php站点的请求,访问到请求所选择的location。
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会按顺序使用配置中的location的正则表达式匹配地址。当匹配成功时,nginx会停止查找并且使用该location。如果请求没有和任何正则表达式匹配成功,那么nginx会使用之前查找到的最明确的location前缀。
值得注意的是,所有类型的location配置只会和请求的URI部分进行匹配,不包括变量。这是因为请求中的变量可能会以好多种方式出现,如下所示:
/index.php?user=john&page=1
/index.php?page=1&user=john
任何人都可以在请求字符串中请求任意事物。
/index.php?page=1&something+else&user=john
接下来了解上述配置是如何处理请求的:
请求”/logo.gif”首先由前缀”/”匹配,然后由正则表达式”\.(gif | jpg | png)$”匹配,因此它将由后一个location处理。使用指令“root/data/www”将请求映射到文件/data/www/logo.gif,并将文件发送到客户端。
请求”/index.php”首先由前缀”/”匹配,然后由正则表达式”\.(php)$”匹配。因此它将由后一个location处理,并且被转发到监听着location:9000端口的FastCGI服务器。fastcgi_param指令将FastCGI变量SCRIPT_FILENAME设置为”/data/www/index.php”,然后FastCGI执行该文件。变量$document_root变量等于root指令的值,变量$fastcgi_script_name等于请求的URI,即”/index.php”。
请求”/about.html”只由前缀”/”匹配,因此将由该location处理。使用指令”root /data/www”将请求映射到文件/data/www/about.html,然后发送到客户端。
处理请求”/”比较复杂。它只匹配了前缀”/”,因此由该location处理。然后index指令根据设置的变量以及”root /data/www”指令检查index文件是否存在。如果/data/www/index.html不存在,/data/www/index.php存在,会内部重定向到”index.php”,然后nginx再次使用这个地址搜索合适的location。正如我们之前所看到的,重定向的请求最终会被FastCGI服务器处理。
Igor Sysoev写作
Brian Mercer修改
kailuncen 翻译