×
新网 > 域名资讯 > 正文

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

当Nginx收到请求后,Nginx分成两部分进行,包括server_name和URL,首先Nginx通过server_name匹配来确定使用哪个server块来处理请求。 分 析 当用户的访问通过网络与nginx建立连接后,nginx首先通过http协议里Request Headers中的Host字段来解析成server_name. 这里我们使用curl命令来查看。如果提示无该命令,centos

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

分 析

de110255c35179596938e99c33f83d34.jpg

当用户的访问通过网络与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, "~^(?<user>.+).example.net$")

性能优化

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,即处理阶段。

  • 相关专题

免责声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,也不承认相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,请发送邮件至:operations@xinnet.com进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

免费咨询获取折扣

Loading