本文参考文章:http://nginx.org/en/docs/http/request_processing.html nginx要处理一个请求,首先得接收到一个请求。 1. 基于名字的虚拟服务器 下面看看这个nginx配置文件的部分配置。 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会去检测一个请求的请求头中是否有header为"Host",然后决定将请求转发到那个服务器上。如果这个"Host"的值没有任何服务器的名字与之相匹配,或者说这次请求没有包含请求头有header为"Host"。那么nginx会将这次请求转发到指定监听端口(*.80)的默认服务器上。 在上面的配置中,第一个server就是默认的服务器,这时nginx默认的标准设置。 当然除了nginx自动设置默认服务器外,我们也可以自己配置这个默认服务器,方式如下: 在listren指令后面添加default_server即可。如: server { listen 80 default_server; server_name example.net www.example.net; ... } 注意: a) default_server是从0.8.21版开始支持的,以前的版本不支持这个设置。 b) default_server是listen指令的一个参数属性,而不是server_name的参数属性。 2. 怎样阻止请求头中没有"Host"的请求被处理 我们可以这样做,将server_name 设置成一个空字符串,这样就能匹配到乜有"Host"请求头的服务器,然后做相应的处理。如:
server { listen 80; server_name ""; return 444; } 3. 基于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地址和端口是否与请求的相匹配。如果没有匹配的就转到默认服务器上处理。 如果有配的ip和端口,然后在通过"Host"这个header来匹配到底选择哪个服务器,如果没有找到名字匹配的服务器,那么请求会被转发到默认的处理服务器上。 如果找到匹配的就给配置的服务器处理。 例如: 来自192.168.1.1:80 host是www.example.com的请求,将会交个默认服务器处理。因为他请求匹配的ip和端口所对应的server中没有host为www.example.com 4. 不同的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; ... } 5. 简单的请求配置 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; } } 下面我们来分析下: 1) 如果请求的是"/logo.gif",首先匹配的location是"/",这是第一个满足条件的路径匹配,然后再去匹配正则表达式为”\.(gif|jpg|png)$"的location,这时第二个满足条件的匹配。最终会使用第二次的匹配路径,因为更长更明确。然后使用root指令指定的路径下去寻找,如"/data/www/logo.gif",最后将找到后资源会返回到客户端。 2) 如果请求的是"/index.php",首先还是会去匹配为"/"的location,然后再去匹配正则表达式为"\.(php)$"的location,根据location的匹配规则,第二次的匹配路径将会被最终使用,这里,请求将会被转发给FastCGI server 监听为localhost:9000的服务器来处理。 fastcgi_param指令设置FastCGI 的参数为SCRIPT_FILENAME,相当于告诉FastCGI server将会按照指定的路径和请求名去执行这个文件。 变量$document_root相当于root指令的值 变量$fastcgi_script_name相当于请求的URI,如"/index.php" 所以最终FastCGI 的参数SCRIPT_FILENAME: /data/www/index.php 3) 如果请求的是"/about.html",唯一匹配的location是"/", 因此会使用root指令指定的路径,这将在这个路径下去找"about.html",所以最终的返回给客户端的是 /data/www/about.html文件。 4) 处理请求"/"是非常复杂的,只会匹配前缀为"/"的location,而index指令则会去检测"root /data/www"下是否有index.html文件,如果"/data/www/index.html"不存在,而"/data/www/index.php"存在,此时则会做一个内部重定向到"/index.php",此时nginx会再做一次为"/index.php"的请求,然后去匹配对应的location。因此最终会将这个请求转发到 FastCGI server来处理 6. 最后简单的介绍一下location的匹配规则 官方的解释是: 1. Directives with the = prefix that match the query exactly. If found, searching stops. 2. All remaining directives with conventional strings, longest match first. If this match used the ^~ prefix, searching stops. 3. Regular expressions, in order of definition in the configuration file. 4. If #3 yielded a match, that result is used. Else the match from #2 is used.
本文简单介绍了,nginx如果转发处理一个请求,也简单介绍了location的匹配规则,有写的不对的地方,希望大家可以指出来,大家一起深刻理解,一起进步。 |