说明
- NP: NGINX Plus
- AG: Admin Guide
- 会话: session
- 上游: upstream
目录
13.Microsoft Exchange Server的负载平衡
1.HTTP负载平衡
本章介绍如何将NGINX和NGINX Plus用作负载均衡器。
2.总览
跨多个应用程序实例的负载平衡是一种用于优化资源利用率,最大化吞吐量,减少延迟和确保容错配置的常用技术。
查看NGINX Plus的负载平衡和扩展网络研讨会,深入了解NGINX用户用于构建大规模,高可用性Web服务的技术。
NGINX和NGINX Plus可以在不同的部署方案中用作非常有效的HTTP负载平衡器。
3.将HTTP流量代理到一组服务器
要开始使用NGINX Plus或NGINX开源对一组服务器的HTTP流量进行负载平衡,首先需要使用上游指令定义该组。 该指令位于http
上下文中。
该组中的服务器使用server
指令配置(不要与定义在NGINX上运行的虚拟服务器的服务器块混淆)。 例如,以下配置定义了一个名为后端的组,并且由三个服务器配置组成(可以在三个以上的实际服务器中解析):
http {
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com;
server 192.0.0.1 backup;
}
}
要将请求传递给服务器组,请在proxy_pass
指令(或针对这些协议的fastcgi_pass
, memcached_pass
, scgi_pass
, uwsgi_pass
指令)中指定组的名称。在下一个示例中,在NGINX上运行的虚拟服务器将传递所有请求到上一个示例中定义的后端(backend )上游组:
server {
location / {
proxy_pass http://backend;
}
}
以下示例结合了以上两个片段,并显示了如何将HTTP请求代理到后端(backend )服务器组。 该组由三台服务器组成,其中两台运行同一应用程序的实例,而第三台是备份服务器。 由于upstream
块中未指定负载平衡算法,因此NGINX使用默认算法Round Robin:
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
server 192.0.0.1 backup;
}
server {
location / {
proxy_pass http://backend;
}
}
}
4.选择负载均衡方法
NGINX开源支持四种负载平衡方法,而NGINX Plus又添加了两种方法:
1.Round Robin –请求在服务器之间平均分配,并考虑了服务器权重。 默认情况下使用此方法(没有启用它的指令):
upstream backend {
# no load balancing method is specified for Round Robin
server backend1.example.com;
server backend2.example.com;
}
2.Least Connections – 将请求发送到活动连接数最少的服务器,同时还要考虑服务器权重:
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
}
3.IP Hash – 根据客户端IP地址确定向其发送请求的服务器。 在这种情况下,将使用IPv4地址的前三个八位字节或整个IPv6地址来计算哈希值。 该方法保证了来自相同地址的请求将到达同一服务器,除非该请求不可用。
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
}
如果其中一台服务器需要暂时从负载平衡循环中删除,则可以使用down
参数对其进行标记,以保留客户端IP地址的当前哈希值。 该服务器要处理的请求将自动发送到组中的下一个服务器:
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
}
4.通用Hash–将请求发送到的服务器是根据用户定义的键确定的,该键可以是文本字符串,变量或组合。 例如,键可以是成对的源IP地址和端口,或者是本示例中的URI:
upstream backend {
hash $request_uri consistent;
server backend1.example.com;
server backend2.example.com;
}
hash指令的可选一致性参数启用ketama 一致性哈希负载平衡。 根据用户定义的哈希键值,请求将平均分布在所有上游服务器上。 如果将上游服务器添加到上游组或从上游组中删除,则只有少数几个键会被重新映射,从而在负载平衡缓存服务器或其他累积状态的应用程序的情况下最大程度地减少缓存丢失。
5.Least Time (NGINX Plus only) – 对于每个请求,NGINX Plus选择具有最低平均延迟和活动连接数最少的服务器,其中平均延迟是根据包含了last_time指令的以下参数中的哪一个来计算的:
header
– 从服务器接收第一个字节的时间last_byte
– 从服务器接收完整的响应的时间last_byte inflight
– 考虑到请求不完整的情况下,从服务器接收完整响应的时间
upstream backend {
least_time header;
server backend1.example.com;
server backend2.example.com;
}
6.Random – 每个请求将被传递到随机选择的服务器。 如果指定了two
参数,首先,NGINX考虑服务器权重随机选择两个服务器,然后使用指定的方法选择这些服务器之一:
least_conn
– 活动连接数最少least_time=header
(NGINX Plus) – 从服务器接收响应标头的最短平均时间 ($upstream_header_time
)least_time=last_byte
(NGINX Plus) – 从服务器接收完整响应的最短平均时间 ($upstream_response_time
)
upstream backend {
random two least_time=last_byte;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
server backend4.example.com;
}
Random负载均衡方法应用于多个负载均衡器将请求传递到同一组后端的分布式环境。 对于负载平衡器具有所有请求的完整视图的环境,请使用其他负载平衡方法,例如轮询,最少连接和最少时间。
注意:当配置除Round Robin以外的任何方法时,请将相应的伪指令(
hash
,ip_hash
,least_conn
,least_time
,random
)放在upstream {}
块中的服务器伪指令列表上方。
5.服务器权重
默认情况下,NGINX使用Round Robin方法根据请求的权重在组中的服务器之间分配请求。 server
指令的weight
参数设置服务器的权重; 默认值为1:
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com;
server 192.0.0.1 backup;
}
在示例中,backend1.example.com的权重为5
; 其他两台服务器的默认weight (1
),但IP地址为192.0.0.1
的一台服务器被标记为backup
服务器,除非其他两台服务器都不可用,否则不会接收请求。 使用权重的此配置,每6个请求中,有5个发送到backend1.example.com,有1个发送到backend2.example.com。
6.服务器慢启动
服务器缓慢启动功能可防止连接数过多而使最近恢复的服务器不堪重负,因为连接可能会超时并导致服务器再次标记为故障。
在NGINX Plus中,慢速启动允许上游(upstream)服务器在恢复或可用后将其权重(weight)从0逐渐恢复到正常的值。 这可以通过server
指令的slow_start
参数来完成:
upstream backend {
server backend1.example.com slow_start=30s;
server backend2.example.com;
server 192.0.0.1 backup;
}
时间值(此处为30秒)将NGINX Plus将与服务器的连接数增加到完整值的时间。
请注意,如果组中只有一台服务器,则将忽略server
指令的max_fails
, fail_timeout
, slow_start
参数,并且永远不会将服务器视为不可用。
7.启用Session持久性
Session持久性意味着NGINX Plus可以识别用户会话并将给定会话中的所有请求路由到同一上游(upstream)服务器。
NGINX Plus支持三种session持久性方法。 这些方法是使用sticky
指令设置的。 (对于NGINX开源的session持久性,请使用如上所述的hash
或ip_hash
指令。)
- Sticky cookie – NGINX Plus将session cookie添加到上游(upstream)组的第一个响应中,并标识发送响应的服务器。 客户端的下一个请求包含cookie值,NGINX Plus将请求路由到响应第一个请求的上游(upstream)服务器:
upstream backend {
server backend1.example.com;
server backend2.example.com;
sticky cookie srv_id expires=1h domain=.example.com path=/;
}
在示例中,srv_id
参数设置cookie的名称。 可选的expires
参数设置浏览器保留cookie的时间(此处为1小时)。 可选的domain
参数定义了为其设置cookie的域,而可选的path
参数定义了为其设置cookie的路径。 这是最简单的会话(session)持久性方法。
- Sticky route – NGINX Plus在收到第一个请求时为客户端分配一个“route”。 将所有后续请求与服务器指令的
route
参数进行比较,以标识请求所代理的服务器。route信息来自Cookie或请求URI。
upstream backend {
server backend1.example.com route=a;
server backend2.example.com route=b;
sticky route $route_cookie $route_uri;
}
- Sticky learn 方法– NGINX Plus首先通过检查请求和响应来找到会话(session)标识符。 然后NGINX Plus“learns”哪个上游(upstream)服务器对应于哪个会话(session)标识符。 通常,这些标识符在HTTP cookie中传递。 如果请求中包含已经''learned''的会话(session)标识符,NGINX Plus将请求转发到相应的服务器:
upstream backend {
server backend1.example.com;
server backend2.example.com;
sticky learn
create=$upstream_cookie_examplecookie
lookup=$cookie_examplecookie
zone=client_sessions:1m
timeout=1h;
}
在该示例中,上游(upstream)服务器之一通过在响应中设置cookie EXAMPLECOOKIE
来创建会话(session)。
必需的create
参数指定一个变量,该变量指示如何创建新会话(session)。 在该示例中,新会话(session)是根据上游(upstream)服务器发送的Cookie EXAMPLECOOKIE
创建的。
强制性查找参数指定如何搜索现有会话。 在我们的示例中,现有会话(sessions)是在客户端发送的Cookie EXAMPLECOOKIE
中搜索的。
强制zone
参数指定一个共享内存区域,其中保留了有关粘性会话(session)的所有信息。 在我们的示例中,该zone名为client_sessions,大小为1 MB。
与前两种方法相比,这是一种更复杂的会话(session)持久性方法,因为它不需要在客户端保留任何cookie:所有信息都在共享存储区域的服务器端保留。
如果集群中有多个使用“sticky learn”方法的NGINX实例,则可以在以下条件下同步其共享内存区域的内容:
- 区域具有相同的名称
- 在每个实例上配置了
zone_sync
功能 - 指定了
sync
参数
sticky learn
create=$upstream_cookie_examplecookie
lookup=$cookie_examplecookie
zone=client_sessions:1m
timeout=1h
sync;
}
有关详细信息,请参见群集中的运行时状态共享。
8.限制连接数
使用NGINX Plus,可以通过使用 max_conns
参数指定最大数量来限制到上游(upstream)服务器的连接数量。
如果已达到max_conns
限制,则将请求放置在队列中以进行进一步处理,前提是还包括queue
指令来设置队列中可以同时存在的最大请求数:
upstream backend {
server backend1.example.com max_conns=3;
server backend2.example.com;
queue 100 timeout=70;
}
如果队列中充满了请求,或者在可选的timeout
参数指定的超时期间无法选择上游(upstream)服务器,则客户端会收到错误消息。
请注意,如果在其他工作进程中打开了空闲的保持活动(keepalive)连接,则会忽略max_conns
限制。 结果,在与多个工作进程共享内存的配置中,与服务器的连接总数可能会超过max_conns
值。
9.配置健康检查
NGINX可以持续测试你的HTTP上游(upstream)服务器,避免出现故障的服务器,并可以将恢复的服务器正常地添加到负载平衡组中。
请参阅HTTP运行状况检查以获取有关如何配置HTTP运行状况检查的说明。
10.与多个工作进程共享数据
如果上游(upstream
)块不包含zone
指令,则每个工作进程将保留其自己的服务器组配置复本,并维护其自己的一组相关计数器。 计数器包括与组中每个服务器的当前连接数以及将请求传递给服务器的尝试失败次数。 结果,服务器组配置无法动态修改。
当zone
指令包含在upstream
块中时,上游组的配置将保留在所有工作进程之间共享的存储区中。 此方案是可动态配置的,因为工作进程访问组配置的相同复本并利用相同的相关计数器。
zone
指令对于主动运行状况检查和上游组的动态重新配置是必需的。 但是,上游(upstream)组的其他功能也可以从此指令的使用中受益。
例如,如果未共享组的配置,则每个工作进程都会维护自己的计数器,以防止将请求传递到服务器的尝试失败(由max_fails
参数设置)。在这种情况下,每个请求仅到达一个工作进程。当被选择来处理请求的工作进程不能发送请求到服务器,其他工作进程不知道有这回事。 尽管某些工作进程可以认为服务器不可用,但其他工作进程仍可能向该服务器发送请求。 为了使服务器确定不可用,在fail_timeout
参数设置的时间范围内,失败尝试的次数必须等于max_fails
乘以辅助进程的数量。 另一方面,zone
指令保证了预期的行为。
同样,至少在低负载下,如果没有zone
指令,“最少连接”负载平衡方法可能无法按预期工作。 此方法将活动连接数量最少的请求传递到服务器。 如果未共享组的配置,则每个工作进程将使用其自己的计数器作为连接数,并且可能将请求发送到与另一个工作进程刚刚向其发送请求的服务器相同的服务器。 但是,你可以增加请求数以减少这种影响。 在高负载下,请求在工作进程之间平均分配,并且“最少连接”方法按预期工作。
11.设定区域(Zone)大小
由于使用模式差异很大,因此没有理想的存储区大小。 所需的内存量取决于启用了哪些功能(例如会话(session)持久性,运行状况检查或DNS重新解析)以及如何标识上游(upstream)服务器。
例如,通过启用sticky_route
会话持久性方法和单个运行状况检查,一个256 KB的区域可以容纳有关指示数量的上游服务器的信息:
- 128 服务器 (每个定义为IP address:port 对)
- 88 服务器 (每个定义为hostname:port对,其中主机名解析为单个IP地址)
- 12 服务器 (每个定义为hostname:port对,其中主机名解析为多个IP地址)
12.使用DNS配置HTTP负载平衡
可以在运行时使用DNS修改服务器组的配置。
对于在server
指令中用域名标识的上游组中的服务器,NGINX Plus可以监视对相应DNS记录中IP地址列表的更改,并自动将更改应用于上游组的负载平衡,而无需重新启动。 这可以通过在http
块中包括resolver
指令以及server
指令的resolve
参数来完成:
http {
resolver 10.0.0.1 valid=300s ipv6=off;
resolver_timeout 10s;
server {
location / {
proxy_pass http://backend;
}
}
upstream backend {
zone backend 32k;
least_conn;
# ...
server backend1.example.com resolve;
server backend2.example.com resolve;
}
}
在示例中,server
指令的resolve
参数告诉NGINX Plus定期将backend1.example.com和backend2.example.com域名重新解析为IP地址。
解析器(resolver
)指令定义了NGINX Plus向其发送请求的DNS服务器的IP地址(此处为10.0.0.1)。 默认情况下,NGINX Plus以记录中的生存时间(TTL)指定的频率重新解析DNS记录,但是你可以使用valid
参数覆盖TTL值; 在此示例中,时间为300秒或5分钟。
可选的ipv6=off
参数表示仅IPv4地址用于负载平衡,尽管默认情况下支持解析IPv4和IPv6地址。
如果域名解析为多个IP地址,则这些地址将保存到上游配置并进行负载平衡。 在我们的示例中,根据最小连接负载平衡方法对服务器进行了负载平衡。 如果服务器的IP地址列表已更改,NGINX Plus将立即开始在新地址集上进行负载平衡。
13.Microsoft Exchange Server的负载平衡
在NGINX Plus R7和更高版本中,NGINX Plus可以将Microsoft Exchange通信代理到一个服务器或一组服务器,并对其进行负载平衡。
1.在一个location
块中,使用proxy_pass
指令配置到Microsoft Exchange服务器上游组的代理:
location / {
proxy_pass https://exchange;
# ...
}
2.为了使Microsoft Exchange连接传递到上游服务器,请在位置块中将proxy_http_version
伪指令值设置为1.1,并将proxy_set_header
伪指令设置为Connection ""
,就像保持连接一样:
location / {
# ...
proxy_http_version 1.1;
proxy_set_header Connection "";
# ...
}
3.在http
块中,为Microsoft Exchange服务器的上游组配置一个上游块,该上游块的名称与在步骤1中使用proxy_pass
指令指定的上游组相同。然后指定ntlm
指令,以允许该组中的服务器接受NTLM的请求。 验证:
http {
# ...
upstream exchange {
zone exchange 64k;
ntlm;
# ...
}
}
4.将Microsoft Exchange服务器添加到上游组,并可以选择指定负载平衡方法:
http {
# ...
upstream exchange {
zone exchange 64k;
ntlm;
server exchange1.example.com;
server exchange2.example.com;
# ...
}
}
14.完整的NTLM示例
http {
# ...
upstream exchange {
zone exchange 64k;
ntlm;
server exchange1.example.com;
server exchange2.example.com;
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/company.com.crt;
ssl_certificate_key /etc/nginx/ssl/company.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
proxy_pass https://exchange;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}
有关配置Microsoft Exchange和NGINX Plus的详细信息,请参阅使用NGINX Plus部署负载平衡Microsoft Exchange Server部署指南。
15.使用NGINX Plus API进行动态配置
使用NGINX Plus,可以使用NGINX Plus API动态修改上游服务器组的配置。 配置命令可用于查看所有服务器或组中的特定服务器,修改特定服务器的参数以及添加或删除服务器。 有关更多信息和说明,请参阅使用NGINX Plus API配置动态负载平衡。