Nginx-服务器名称

服务器名称使用server_name指令来定义,确定请求使用哪个server块。可以使用确切的名称、通配符名称或正则表达式来定义它们:

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$;
    ...
}

当通过名称搜索虚拟服务器时,如果名称匹配多个指定的变量,例如通配符名称和正则表达式都匹配,则将按照以下优先顺序选择第一个匹配变量:

  1. 确切的名称
  2. 以星号开头的最长通配符名称,例如:“*.example.org”
  3. 以星号结尾的最长通配符名称,例如:“mail.*”
  4. 第一个匹配的正则表达式(按在配置文件中出现的顺序)

通配符名称

通配符名称只能在名称的开始或结尾处包含星号,并且只能在点边界上包含星号。名称“www.*.example.org”和“w*.example.org”都是无效的。但是,可以使用正则表达式指定这些名称,例如“~^www\…+\.example\.orgKaTeX parse error: Undefined control sequence: \* at position 8: ”和“~^w.\̲*̲\\.example\\.or…”。星号可以匹配多个名称部分,例如:“*.example.org”不仅匹配“www.example.org”,而且匹配“www.sub.example.org”

另外,还有一种特殊的通配符形式“.example.org”,他既可以匹配“example.org”,也可以匹配“*.example.org”

正则表达式名称

Nginx使用的正则表达式与Perl编程语言使用的正则表达式兼容。要使用正则表达式,server_name指令的值必须以“~”开头:

server_name ~^www\d+\.example\.net$;

否则,它将被视为确切的名称,或者如果表达式包含星号,则被视为通配符名称(并且很可能是无效的名称)。不要忘记设置“^”和“$”锚。他们在语法上不是必须的,但是在逻辑上是必须的。还有一点需要注意,域名中的点应该使用反斜杆转义。一个包含字符“{”和“}”的正则表达式应该使用引号包裹:

server_name "~^(?<name>\w\d{1, 3}+)\.example\.net$";

否则,Nginx将无法启动并显示错误信息。正则表达式匹配的内容可以被捕捉为变量使用,如下:

server {
    server_name ~^(www\.)?(?<domain>.+)$;
    location / {
        root /sites/$domain;
    }
}

PCRE库支持以下语法命名捕捉:

  • ?<name>: Perl5.10兼容语法,自PCRE-7.0起受支持
  • ?'name': Perl5.10兼容语法,自PCRE-7.0起受支持
  • ?P<name>: 自PCRE-4.0起受支持的Python兼容语法

如果Nginx无法启动并显示错误信息:

pcre_compile() failed: unrecognized character after (?< in ...

这意味着PCRE库很老旧,应尝试使用?P<name>替代。

正则表达式匹配的内容捕捉,也可以使用数字形式,如下:

server {
    server_name ~^(www\.)?(.+)$;
    location / {
        root /site/$2;
    }
}

其中“$2”表示正则表达式中匹配到的第二个内容。上面栗子中,如下传递的“Host”为“www.baidu.com”,那么匹配到“$2”将会是“baidu.com”。

杂项名称

如果需要server块中处理没有“Host”标头字段的额请求,则应指定空名称:

server {
    listen 80;
    server_name example.org www.example.org "";
    ...
}

如果在server块中未定义server_name,则Nginx使用空名称作为服务器名称。

如果server_name定义为$hostname,则使用计算机的主机名。

如果有人使用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 _;
    rerturn 444;
}

这个名称没有什么特别之处,它只是无数无效域名中的一个,这些域名与任何真实的名称都没有交集。同样也可以使用其他的无效名称,例如:“–”和“!@#”

国际化名称

应在server_name指令中使用ASCII表示来指定国际化域名:

server {
    listen 80;
    server_name xn--e1afmkfd.xn--80akhbyknj4f;
    ...
}

优化

确切的名称、以星号开头的通配符名称和以星号结尾的通配符名称存储在绑定到侦听端口的三个哈希表中。哈希表的大小在配置阶段进行了优化,以便能够以最少的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_sizeserver_names_hash_bucket_size指令。server_names_hash_bucket_size指令的默认值可能是32、64或其他值,这取决于CPU缓存线的大小。如果定义了异常长的服务器名称,导致Nginx无法启动并显示错误信息:

could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32

在这种情况之下,应该将指令的值升到2的下一次幂的值,如下:

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指令的值。

发布了158 篇原创文章 · 获赞 115 · 访问量 52万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章