服务器名称是使用 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 ~^(?.+)\.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 "~^(?\w\d{1,3}+)\.example\.net$";
否则 nginx 将无法启动并且显示错误信息:
directive "server_name" is not terminated by ";" in ...
正则表达式名称捕获到的内容可以作为变量为后面所用:
server {
server_name ~^(www\.)?(?.+)$;
location / {
root /sites/$domain;
}
}
PCRE 库使用以下语法捕获名称:
?
Perl 5.10 兼容语法,自 PCRE-7.0 起支持?'name'
Perl 5.10 兼容语法,自 PCRE-7.0 起支持?P
Python 兼容语法,自 PCRE-4.0 起支持如果 nginx 无法启动并且显示错误信息:
pcre_compile() failed: unrecognized character after (?< in ...
说明 PCRE 库比较老,应该尝试使用语法 ?P
。捕获也可以使用数字形式:
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 请求 header 域将包含 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)表示来指定国际化域名(IDN)
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_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
在这种情况下,指令值应该增加到 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 的值。
如果服务器是监听端口的唯一服务器,那么 nginx 将不会验证服务器名称(并且不会为监听端口建立哈希表)。但是,有一个例外。如果服务器名称具有捕获(captures)的正则表达式,则 nginx 必须执行表达式才能获取捕获。
$hostname
。""
。""
。example.*
的通配符。.example.org
。*.example.org
的通配符。由 Igor Sysoev 书写,由 Brian Mercer 编辑
负载均衡跨越多个应用程序实例,是一种常用的技术,其用于优化资源利用率、最大化吞吐量、减少延迟和确保容错配置。
可以使用 nginx 作为高效的 HTTP 负载均衡器,将流量分布到多个应用服务器,并通过 nginx 提高 web 应用程序的性能、可扩展性和可靠性。
nginx 支持以下负载均衡机制(或方法):
使用 nginx 进行负载均衡的最简单配置如下所示:
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}
在上述示例中,在 srv1-srv3 上运行相同的应用的三个实例。当负载均衡方法没有被特别配置时,默认采用轮询(round-robin)。所有请求都被 代理 到服务器组 myapp1,nginx 应用 HTTP 负载均衡来分发请求。
nginx 中的反向代理实现包括 HTTP、HTTPS、FastCGI、uwsgi、SCGI 和 memcached。
要配置 HTTPS 而不是 HTTP 负载均衡,只需要使用 HTTPS 协议。
在为 FastCGI、uwsgi、SCGI 或 memcached 设置负载均衡时,分别使用 fastcgi_pass、uwsgi_pass、scgi_pass 和 memcached_pass 指令。
另一个负载均衡的规则是最少连接。在一些请求需要更长的时间才能完成的情况下,最少连接可以更公正地控制应用程序实例的负载。
使用最少连接的负载均衡,nginx 将尽量不给过于繁忙的应用服务器负载过多的请求,而是将新的请求分发到不太忙的服务器。
当使用 least_conn 指令作为服务组配置的一部分时,将激活 nginx 中的最少连接负载均衡:
upstream myapp1 {
least_conn;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
请注意,使用轮询或者最少连接的负载均衡,每个后续客户端的请求都可能被分配到不同的服务器。不能保证同一个客户端始终指向同一个服务器。
如果需要将客户端绑定到特定的应用服务器,换而言之,使客户端会话「粘滞」或者「永久」,始终尝试选择特定的服务器,IP 哈希负载均衡机制可以做到这点。
使用 IP 哈希,客户端的 IP 地址用作为哈希键,以确定应用为客户端请求选择服务器组中的哪个服务器。此方法确保了来自同一个客户端的请求始终被定向到同一台服务器,除非该服务器不可用。
要配置 IP 哈希负载均衡,只需要将 ip_hash 指令添加到服务器 upstream 组配置中即可:
upstream myapp1 {
ip_hash;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
还可以通过使用服务器权重进一步加强 nginx 的负载均衡算法。
在上面的示例中,服务器权重没有被配置,这意味对于特定的负载均衡方法来说所有指定的服务器都具有同等资格。
特别是使用轮询方式,这也意味着服务器上的请求分配或多或少都是相等的 —— 只要有足够的请求,并且以统一的方式足够快速地完成请求处理。
当服务器指定 weight 参数时,权重将作为负载均衡决策的一部分进行核算。
upstream myapp1 {
server srv1.example.com weight=3;
server srv2.example.com;
server srv3.example.com;
}
通过这样配置,每 5 个新的请求将分布在应用程序实例之中,如下所示:三个请求被定向到 srv1,一个请求将转到 srv2,另一个请求将转到 srv3。
在 nginx 的最近版本中,可以在最少连接和 IP 哈希负载均衡中使用权重。
nginx 中的反向代理实现包括了带内(或者被动)服务器健康检查。如果特定服务器的响应失败并出现错误,则 nginx 会将此服务器标记为失败,并尝试避免为此后续请求选择此服务器而浪费一段时间。
max_fails 用于设置在 fail_timeout 期间与服务器通信失败重新尝试的次数。默认情况下,max_fails 设置为 1。当设置为 0 时,该服务器的健康检查将被禁用。fail_timeout 参数还定义了服务器被标记为失败的时间。在服务器发生故障后的 fail_timeout 间隔后,nginx 开始以实时客户端的请求优雅地探测服务器。如果探测成功,则将服务器标记为活动。
此外,还有更多的指令和参数可以控制 nginx 中的服务器负载均衡,例如,proxy_next_upstream、backup、down 和 keepalive。有关更多的信息,请查看我们的参考文档。
最后但同样重要,应用程序负载均衡、应用程序健康检查、活动监控 和服务组 动态重新配置 作为我们 NGINX Plus 付费订阅的一部分。
以下文章详细介绍了 NGINX Plus 负载均衡: