nginx如何处理请求系列3-server_name指令
当Nginx收到请求后,Nginx分成两部分进行,包括server_name和URL,首先Nginx通过server_name匹配来确定使用哪个server块来处理请求。
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名、网络空间、营销软件、网站建设、高碑店网站维护、网站推广。分 析
当用户的访问通过网络与nginx建立连接后,nginx首先通过http协议里Request Headers中的Host字段来解析成server_name. 这里我们使用curl命令来查看。如果提示无该命令,centos可使用yum -y install curl 来安装。
[root@slave2 ~]# curl localhost -v * About to connect() to localhost port 80 (#0) * Trying ::1... Connection refused * Trying 127.0.0.1... connected * Connected to localhost (127.0.0.1) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: localhost > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.12.2 < Date: Mon, 08 Jan 2018 09:43:50 GMT < Content-Type: text/html < Content-Length: 612 < Last-Modified: Tue, 17 Oct 2017 13:25:44 GMT < Connection: keep-alive < ETag: "59e604d8-264" < Accept-Ranges: bytes < * Connection #0 to host localhost left intact * Closing connection #0
这里注意
> GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: localhost > Accept: */* >
nginx解析该请求,得到当前请求的server_name为localhost。当nginx启动时会加载所有的配置文件,并将配置文件中的server指令定义的块中的server_name加入到server_names_hash中,这里注意,如果没有定义 default_server会多加入一个server_name为default_server的server块。
我们来看如下nginx配置文件,省略部分无影响的配置。
server { listen 80; server_name 172.19.23.208; } server { listen 80; server_name test.com; } server { listen 808; server_name 172.19.23.208; }
Note对于test.com,你可能需要通过指定hosts文件来使该域名访问到nginx。
[root@slave2 ~]# curl 172.19.23.208:808 -v * About to connect() to 172.19.23.208 port 808 (#0) * Trying 172.19.23.208... connected * Connected to 172.19.23.208 (172.19.23.208) port 808 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: 172.19.23.208:808 > Accept: */* > < HTTP/1.1 404 Not Found < Server: nginx/1.12.2 < Date: Mon, 08 Jan 2018 10:03:39 GMT < Content-Type: text/html < Content-Length: 169 < Connection: keep-alive <
注意Host字段变成172.19.23.208:808,nginx解析它,server_name为172.19.23.208,port为808,port在server_name匹配前已使用,所以nginx会使用配置段
server { listen 808; server_name 172.19.23.208; }
来处理该请求,至于请求后续的处理,后面来看。
这里要知道,nginx的server匹配是有优先级的,官方文档,这在host能匹配多个server块时尤其重要。 匹配原则如下
exact name 精确名(eg "www.test.com","172.19.23.208") longest wildcard name starting with an asterisk, e.g. “*.example.org” 星号开始的最长通配符名 longest wildcard name ending with an asterisk, e.g. “mail.*” 星号结束的最长通配符名 first matching regular expression (in order of appearance in a configuration file) 最先匹配的正则表达式名(除开星号开始和结束的正则表达式 eg, "~^(?性能优化
Exact names, 星号开始的最长通配符名,星号结束的最长通配符名在三个哈希表中,哈希表的尺寸在configuration phase进行了优化,这里有一点点性能不同, server_name按照域名来搜索的,所以exact names速度最快。注意.example.org储存在星号开始的最长通配符名的哈希表中。 正则表达式是串行测试,所以最慢,且不可扩展。
所以请尽可能使用exact name。example.org和www.example.org被访问得最频繁的,那么将它们明确的定义出来效果就会更好。
server { listen 80; server_name example.org www.example.org *.example.org; ... }
实际书写nginx配置文件时,尽量使用exact name作为server_name 这样一目了然,同时避免新手歧义,也带来性能提升。、
这里有两个参数
server_names_hash_max_size server_name哈希表空间,等同于为python字典设置了key的个数。 server_names_hash_bucket_size server_name长度,等同于python字典string value的长度。
比如:
server { server_name too.long.server.name.example.org; }
启动(或reload)提示
could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
处理:
http { server_names_hash_bucket_size 64; ... }
另一个我们有个托管的虚拟主机,有大量的server_name需要引入时:
could not build the server_names_hash, you should increase either server_names_hash_max_size: 512 or server_names_hash_bucket_size: 32
先尝试设置server_names_hash_max_size的值差不多等于哈希表key的总数。如果没用,或者服务器启动非常缓慢,再提高server_names_hash_bucket_size的值。
如果只为一个监听端口配置了唯一的主机,那么nginx就完全不会测试虚拟主机名了(也不会为监听端口建立哈希表)。但有一个例外,如果定义的虚拟主机名是一个含有捕获组的正则表达式,这时nginx就不得不执行这个表达式以得到捕获组。
当server_name匹配完成后,便会进行nginx的phase handler,即处理阶段。
本文题目:nginx如何处理请求系列3-server_name指令
转载源于:http://ybzwz.com/article/cgejsj.html