nginx 如何处理请求系列3-server_name指令

阅读:366 2019-03-19 15:04:05 来源:开源中国

当nginx收到请求后,nginx分成两部分进行,包括server_name和url,首先nginx通过server_name匹配来确定使用哪个server块来处理请求。

分析

当用户的访问通过网络与nginx建立连接后,nginx首先通过http协议里requestheaders中的host字段来解析成server_name.这里我们使用curl命令来查看。如果提示无该命令,centos可使用yum-yinstallcurl来安装。

[root@slave2~]#curllocalhost-v*abouttoconnect()tolocalhostport80(#0)*trying::1...connectionrefused*trying127.0.0.1...connected*connectedtolocalhost(127.0.0.1)port80(#0)>get/http/1.1>user-agent:curl/7.19.7(x86_64-redhat-linux-gnu)libcurl/7.19.7nss/3.16.2.3basicecczlib/1.2.3libidn/1.18libssh2/1.4.2>host:localhost>accept:*/*>

这里注意

>get/http/1.1>user-agent:curl/7.19.7(x86_64-redhat-linux-gnu)libcurl/7.19.7nss/3.16.2.3basicecczlib/1.2.3libidn/1.18libssh2/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{listen80;server_name172.19.23.208;}server{listen80;server_nametest.com;}server{listen808;server_name172.19.23.208;}

note对于test.com,你可能需要通过指定hosts文件来使该域名访问到nginx。

[root@slave2~]#curl172.19.23.208:808-v*abouttoconnect()to172.19.23.208port808(#0)*trying172.19.23.208...connected*connectedto172.19.23.208(172.19.23.208)port808(#0)>get/http/1.1>user-agent:curl/7.19.7(x86_64-redhat-linux-gnu)libcurl/7.19.7nss/3.16.2.3basicecczlib/1.2.3libidn/1.18libssh2/1.4.2>host:172.19.23.208:808>accept:*/*>

注意host字段变成172.19.23.208:808,nginx解析它,server_name为172.19.23.208,port为808,port在server_name匹配前已使用,所以nginx会使用配置段

server{listen808;server_name172.19.23.208;}

来处理该请求,至于请求后续的处理,后面来看。

这里要知道,nginx的server匹配是有优先级的,官方文档,这在host能匹配多个server块时尤其重要。匹配原则如下

性能优化

exactnames,星号开始的最长通配符名,星号结束的最长通配符名在三个哈希表中,哈希表的尺寸在configurationphase进行了优化,这里有一点点性能不同,server_name按照域名来搜索的,所以exactnames速度最快。注意.example.org储存在星号开始的最长通配符名的哈希表中。正则表达式是串行测试,所以最慢,且不可扩展。

所以请尽可能使用exactname。example.org和www.example.org被访问得最频繁的,那么将它们明确的定义出来效果就会更好。

server{listen80;server_nameexample.orgwww.example.org*.example.org;...}

实际书写nginx配置文件时,尽量使用exactname作为server_name这样一目了然,同时避免新手歧义,也带来性能提升。、

这里有两个参数

server_names_hash_max_sizeserver_name哈希表空间最大,等同于为python字典设置了最大key的个数。server_names_hash_bucket_sizeserver_name最大长度,等同于python字典stringvalue的最大长度。

比如:

server{server_nametoo.long.server.name.example.org;}

启动(或reload)提示

couldnotbuildtheserver_names_hash,youshouldincreaseserver_names_hash_bucket_size:32

处理:

http{server_names_hash_bucket_size64;...}

另一个我们有个托管的虚拟主机,有大量的server_name需要引入时:

couldnotbuildtheserver_names_hash,youshouldincreaseeitherserver_names_hash_max_size:512orserver_names_hash_bucket_size:32

先尝试设置server_names_hash_max_size的值差不多等于哈希表key的总数。如果没用,或者服务器启动非常缓慢,再提高server_names_hash_bucket_size的值。

如果只为一个监听端口配置了唯一的主机,那么nginx就完全不会测试虚拟主机名了(也不会为监听端口建立哈希表)。但有一个例外,如果定义的虚拟主机名是一个含有捕获组的正则表达式,这时nginx就不得不执行这个表达式以得到捕获组。

相关文章
{{ v.title }}
{{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
你可能感兴趣
推荐阅读 更多>
推荐商标

{{ v.name }}

{{ v.cls }}类

立即购买 联系客服