服务器名称
通配符名称 正则表达式名称 其他名称 国际化名称 虚拟服务器选择 优化 兼容性 |
服务器名称通过 server_name 指令定义,并确定了给定请求使用哪个 server 块。参见“nginx 如何处理请求”。它们可以使用精确名称、通配符名称或正则表达式定义:
server { listen 80; server_name example.org www.example.org; ... } server { listen 80; server_name *.example.org; ... } server { listen 80; server_name mail.*; ... } server { listen 80; server_name ~^(?<user>.+)\.example\.net$; ... }
在按名称搜索虚拟服务器时,如果名称匹配多个指定的变体,例如,通配符名称和正则表达式都匹配,将选择第一个匹配的变体,按以下优先顺序:
- 精确名称
- 以星号开头的最长通配符名称,例如“
*.example.org
” - 以星号结尾的最长通配符名称,例如“
mail.*
” - 第一个匹配的正则表达式(按配置文件中的出现顺序)
通配符名称
通配符名称只能在名称的开头或结尾以及点边界上包含星号。名称“www.*.example.org
”和“w*.example.org
”是无效的。但是,这些名称可以使用正则表达式指定,例如“~^www\..+\.example\.org$
”和“~^w.*\.example\.org$
”。星号可以匹配多个名称部分。名称“*.example.org
”不仅匹配 www.example.org
还匹配 www.sub.example.org
。
形如“.example.org
”的特殊通配符名称可以用于匹配精确名称“example.org
”和通配符名称“*.example.org
”。
正则表达式名称
nginx 使用的正则表达式与 Perl 编程语言(PCRE)兼容。要使用正则表达式,服务器名称必须以波浪符号开头:
server_name ~^www\d+\.example\.net$;
否则将被视为精确名称,或者如果表达式包含星号,则被视为通配符名称(并且很可能是无效的)。不要忘记设置“^
”和“$
”锚点。它们在语法上不是必需的,但在逻辑上是必需的。还要注意,域名点应该用反斜杠转义。包含字符“{
”和“}
”的正则表达式应该加引号:
server_name "~^(?<name>\w\d{1,3}+)\.example\.net$";
否则 nginx 将无法启动并显示错误消息:
directive "server_name" is not terminated by ";" in ...
以后可以使用命名的正则表达式捕获作为变量:
server { server_name ~^(www\.)?(?<domain>.+)$; location / { root /sites/$domain; } }
PCRE 库支持使用以下语法进行命名捕获:
If nginx fails to start and displays the error message:
?<
name
>Perl 5.10 兼容的语法,自 PCRE-7.0 起支持 ?'
name
'Perl 5.10 兼容的语法,自 PCRE-7.0 起支持 ?P<
name
>Python 兼容的语法,自 PCRE-4.0 起支持
pcre_compile() failed: unrecognized character after (?< in ...
这意味着 PCRE 库比较旧,应尝试使用语法“?P<
”。捕获还可以以数字形式使用:name
>
server { server_name ~^(www\.)?(.+)$; location / { root /sites/$2; } }
然而,此类用法应仅限于简单情况(如上所述),因为数字引用很容易被覆盖。
杂项名称
有一些服务器名称被特殊处理。
如果需要在非默认的 server 块中处理没有“Host”头字段的请求,则应指定一个空名称:
server { listen 80; server_name example.org www.example.org ""; ... }
如果在 server 块中未定义 server_name ,则 nginx 使用空名称作为服务器名称。
nginx 版本直到 0.8.48 在这种情况下使用机器的主机名作为服务器名。
如果将服务器名定义为“$hostname
” (0.9.4),则使用机器的主机名。
如果有人使用 IP 地址而不是服务器名发出请求,则“Host”请求头字段将包含 IP 地址,请求可以使用 IP 地址作为服务器名处理:
server { listen 80; server_name example.org www.example.org "" 192.168.1.1 ; ... }
在通配服务器示例中可以看到奇怪的名称“_
”:
server { listen 80 default_server; server_name _; return 444; }
此名称没有特殊之处,它只是众多无效域名中的一个,永远不会与任何真实名称相交。其他无效名称如“--
” 和 “!@#
” 也可以使用。
nginx 版本直到 0.6.25 支持特殊名称“*
”,错误地被解释为通配名。它从未作为通配或通配符服务器名起作用。相反,它提供了现在由 server_name_in_redirect 指令提供的功能。“*
” 特殊名称现已弃用,应使用 server_name_in_redirect 指令。请注意,没有办法使用 server_name 指令指定通配名或默认服务器。这是 listen 指令的属性,而不是 server_name 指令的属性。另请参阅“nginx 如何处理请求”。可以定义监听端口 *:80 和 *:8080 的服务器,并指定一个将是端口 *:8080 的默认服务器,而另一个将是端口 *:80 的默认服务器:
server { listen 80; listen 8080 default_server; server_name example.net; ... } server { listen 80 default_server; listen 8080; server_name example.org; ... }
国际化名称
应在 server_name 指令中使用 ASCII(Punycode)表示法指定国际化域名 (IDNs):
server { listen 80; server_name xn--e1afmkfd.xn--80akhbyknj4f; # пример.испытание ... }
虚拟服务器选择
首先,在默认服务器上下文中创建连接。然后,在以下请求处理阶段中可以确定服务器名称,每个阶段都涉及服务器配置选择:
-
在 SSL 握手期间,根据 SNI 提前
-
处理请求行后
-
处理
Host
头字段后 -
如果在处理请求行或从
Host
头字段获取服务器名称后未确定服务器名称,则 nginx 将使用空名称作为服务器名称。
在每个阶段,可以应用不同的服务器配置。因此,应谨慎指定某些指令:
- 在ssl_protocols指令的情况下,在通过SNI请求的名称之前,OpenSSL库设置协议列表,因此,应仅为默认服务器指定协议;
- 在读取请求行之前,涉及client_header_buffer_size和merge_slashes指令,因此,此类指令使用默认服务器配置或通过SNI选择的服务器配置;
- 在处理请求头字段时涉及ignore_invalid_headers、large_client_header_buffers和underscores_in_headers指令,还取决于是否根据请求行或
Host
头字段更新了服务器配置; - 错误响应将由当前满足请求的服务器中的error_page指令处理。
优化
精确名称、以星号开头的通配符名称和以星号结尾的通配符名称存储在绑定到监听端口的三个哈希表中。哈希表的大小在配置阶段进行了优化,以便以最少的CPU缓存未命中找到名称。关于设置哈希表的详细信息,请参见单独的文档。
首先搜索精确名称哈希表。如果找不到名称,则搜索以星号开头的通配符名称哈希表。如果在那里找不到名称,则搜索以星号结尾的通配符名称哈希表。
搜索通配符名称哈希表比搜索精确名称哈希表慢,因为名称是按域部分搜索的。请注意,特殊的通配符形式“.example.org
”存储在通配符名称哈希表中,而不是精确名称哈希表中。
正则表达式是按顺序测试的,因此是最慢的方法,而且不可扩展。
因此,最好尽可能使用精确名称。例如,如果服务器最常请求的名称是example.org
和www.example.org
,则明确定义它们比使用简化形式更有效:
server { listen 80; server_name example.org www.example.org *.example.org; ... }
而不是使用简化形式:
server { listen 80; server_name .example.org; ... }
如果定义了大量服务器名称,或者定义了异常长的服务器名称,则可能需要调整http级别的server_names_hash_max_size和server_names_hash_bucket_size指令。server_names_hash_bucket_size指令的默认值可能等于32或64,或者另一个值,具体取决于CPU缓存行大小。如果默认值为32,并且服务器名称定义为“too.long.server.name.example.org
”,则nginx将无法启动,并显示错误消息:
could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
在这种情况下,应该将指令值增加到下一个二次幂:
http { server_names_hash_bucket_size 64; ...
如果定义了大量的服务器名,则会出现另一个错误消息:
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 设置为接近服务器名数量的数字。只有这样做没有帮助,或者nginx的启动时间不可接受长时,才尝试增加 server_names_hash_bucket_size。
如果一个服务器是一个监听端口的唯一服务器,则nginx根本不会测试服务器名(也不会为监听端口构建哈希表)。然而,有一个例外。如果服务器名是带有捕获的正则表达式,则nginx必须执行表达式以获取捕获。
兼容性
- 特殊服务器名“
$hostname
”自0.9.4版开始支持。 - 默认服务器名值自0.8.48版开始为空名“”。
- 自0.8.25版开始支持具名正则表达式服务器名捕获。
- 自0.7.40版开始支持正则表达式服务器名捕获。
- 自0.7.12版开始支持空服务器名“”。
- 自0.6.25版开始支持作为第一个服务器名使用的通配符服务器名或正则表达式。
- 自0.6.7版开始支持正则表达式服务器名。
- 自0.6.0版开始支持通配符形式
example.*
。 - 自0.3.18版开始支持特殊形式
.example.org
。 - 自0.1.13版开始支持通配符形式
*.example.org
。
作者:Igor Sysoev 编辑:Brian Mercer |