Nginx如何处理请求
前言
本篇博客主要介绍的是Nginx如果处理一个请求,通过本篇博客最后可以掌握Nginx处理请求的一个过程。博客中大部分内容都源自于Nginx的官网,后半部分加入了小编自己运用的实例。
情况1:基于名称的服务器
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”,去决定该请求路由到那个服务器。如果没有匹配的服务器名称或者这个请求没有包含头部字段。那么nginx将会将这个请求路由到默认的服务器。在上面的配置中。这个默认的服务器是第一个服务器,这是nginx的默认行为。这个默认的服务器我们也可以进行显示设置,在listen的指令中加上default_server 参数。例如:
server { listen 80 default_server; server_name example.net www.example.net; ...}
情况二,如何防止处理未定义服务器名的请求
如何请求中没有“Host”头部字段,这个请求是不被允许的。
我们可以这样定义一个服务器丢掉这个请求。
server { listen 80; server_name ""; return 444; }
这样定义之后,由于server_name是一个空的字符他将匹配到没有“Host”头部字段的请求。匹配到之后,它将返回一个特殊的非标准的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进行处理。
具体示例:
一个简单的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; } }
$不匹配具体的字符,而是匹配字符串的结尾位置,就是说必须在字符串的结尾匹配到$前面的部分才行,比如:x.gif 能匹配成功而 x.gifa 就不行,与之类似,^ 匹配字符串开始的位置。 \ 这是引用符,用来将这里列出的这些元字符当作普通的字符来进行匹配。 \.表示用点来匹配点字符 *是一个限定符,用来修饰前一个字符或分组,限定匹配重复的数量为任意数量。 ~都是分隔符 没有实际意义一般在php中。
上面正则表达是的含义:
1.~* \.(gif|jpg|png)$:代表匹配所有以.gif 或.jpg或.png结尾的字符 2.~ \.php$:代表匹配所有以.php结尾的字符
nginx一般情况下如何选择一个location来处理一个站点的请求
nginx首先搜索给出的最特定的前缀位置,不管列出的顺序是什么。在上面的配置中唯一的前缀位置是"/"。因为它匹配任何请求,所以它作为最后的匹配策略。然后nginx按照配置文件列出的顺序,从上往下进行匹配,一旦完全匹配上,将停止搜索,nginx将使用用这个位置,如果没有匹配上,那么将使用前面找到的最特定的前缀位置。
现在我们来看在上面的配置中一个请求是如何被处理的。
示例1:
请求/logo.gif,首先找最特定的前缀位置和"/"匹配上,在按照从上到下顺序匹配,最后与.(gif|jpg|png)$匹配上了,然后使用指令root/data/www,请求被映射到文件/data/www/logo.gif,文件被发送到客户端。,最后与.(gif|jpg|png)$匹配上了,然后使用指令root/data/www,请求被映射到文件/data/www/logo.gif,文件被发送到客户端。
示例2:
请求“/about.html”只匹配前缀位置“/”,因此,它在这个位置处理。使用指令“root /data/www”将请求映射到文件/data/www/about.html,并将文件发送到客户端。
示例3:
请求" /index.php “也首先由前缀位置” / “匹配,然后由正则表达式” .(php)$ “匹配。因此,它由后一个位置处理,请求被传递给监听localhost:9000的FastCGI服务器。fastcgi_param指令将FastCGI参数SCRIPT_FILENAME设置为” /data/www/index.php “,然后FastCGI服务器执行该文件。变量d o c u m e n t r o o t 等于根指令的值,变量 document_root等于根指令的值,变量document
r
oot等于根指令的值,变量fastcgi_script_name等于请求的URI,即” /index.php "
示例4:
处理请求“/”更加复杂。它只由前缀位置“/”匹配,因此,它由这个位置处理。然后索引指令根据它的参数和" root /data/www “指令测试索引文件是否存在。
如果/data/www/index.html文件不存在,而/data/www/index.php文件存在,那么该指令会执行一个内部重定向到” /index.php ",然后nginx再次搜索位置,就像请求是由客户端发送的一样。正如我们前面看到的,重定向请求最终将由FastCGI服务器处理。
补充:
当直接访问服务器,另外一点当nginx配置中server中location中有单独配置的如:
root /data/www;
则优先使用location中的路径,如果location中没有配置路径,则使用server块下方配置的
root /data/www;