在《使用NGINX和NGINX Plus实现负载均衡,第1部分》中,我们设置了一个简单的HTTP代理,在多台Web服务器之间对流量进行负载均衡。本文将介绍其他功能,其中部分功能由NGINX Plus提供,包括使用长连接优化性能,以及健康检查、会话持久性、重定向和内容重写。
有关NGINX和NGINX Plus负载均衡功能的详细信息,请参阅《NGINX Plus管理指南》。
编者注:NGINX Plus Release 5及更高版本还可以对基于TCP的应用进行负载均衡。Release 6新增了健康检查、动态重新配置、SSL终止等功能,显著扩展了TCP负载均衡功能。在NGINX Plus Release 7及更高版本中,TCP负载均衡器与HTTP负载均衡器的功能完全一致。UDP负载均衡支持于Release 9中引入。
请在stream上下文中配置TCP和UDP负载均衡,而不是在http上下文中配置。由于HTTP与TCP/UDP存在固有差异,可用的指令和参数也有所不同。有关详细信息,请参阅HTTP和TCP/UDP上游模块的文档。
快速回顾
回顾一下,以下是我们在上一篇文章中构建的配置:
server { listen 80;
location / {
proxy_pass http://backend;
# Rewrite the 'Host' header to the value in the client request,
# or primary server name
proxy_set_header Host $host;
# Alternatively, put the value in the config:
# proxy_set_header Host www.example.com;
}
}
upstream backend {
zone backend 64k; # Use NGINX Plus' shared memory
least_conn;
server webserver1 weight=1;
server webserver2 weight=4;
}本文将介绍几种配置NGINX和NGINX Plus的简单方法,以提升负载均衡的效果。
HTTP持久连接
在NGINX或NGINX Plus与上游服务器之间启用HTTP持久连接,可通过降低延迟来提升性能,并降低NGINX耗尽临时端口的可能性。
HTTP协议使用底层TCP连接来传输HTTP请求和接收HTTP响应。HTTP持久连接支持复用这些TCP连接,从而避免为每个请求创建和销毁连接所产生的开销:
NGINX是一个全代理,可分别管理来自客户端的连接(前端长连接)和到服务器的连接(上游长连接):

NGINX维护一个由上游服务器的空闲keepalive连接组成的“缓存”。需要将请求转发到上游服务器时,NGINX会使用缓存中已建立的keepalive连接,而不是新建TCP连接。这样可以降低NGINX与上游服务器之间的事务延迟,并减缓临时端口的使用速度,使NGINX能够承载大量流量并进行负载均衡。当流量大幅激增时,缓存可能会被耗尽,此时NGINX会与上游服务器建立新的HTTP连接。
在其他负载均衡工具中,这项技术有时称为“多路复用”、“连接池”、“连接复用”或“OneConnect”。
要配置keepalive连接缓存,请在配置中添加“proxy_http_version”、“proxy_set_header”和“keepalive”指令:
server { listen 80;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
upstream backend {
server webserver1;
server webserver2;
# maintain up to 20 idle connections to the group of upstream servers
keepalive 20;
}运行状况检查
启用运行状况检查可提高负载均衡服务的可靠性,降低最终用户看到错误消息的可能性,还有助于执行常见的维护操作。
NGINX Plus中的健康检查功能可用于检测上游服务器故障。NGINX Plus使用“合成事务”探测每台服务器,并根据您在health_check指令中配置的参数检查响应(如果包含match参数,还会根据关联的match配置块进行检查):
server { listen 80;
location / {
proxy_pass http://backend;
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# The health checks inherit other proxy settings
proxy_set_header Host www.foo.com;
}
}
match statusok {
# Used for /test.php health check
status 200;
header Content-Type = text/html;
body ~ "Server[0-9]+ is alive";
}健康检查会从其父级location块继承一些参数。如果在配置中使用运行时变量,可能会导致问题。例如,以下配置适用于实际HTTP流量,因为它会从客户端请求中提取Host标头的值。但它可能不适用于健康检查所使用的合成事务,因为这些事务未设置Host标头,这意味着合成事务中不会使用Host标头。
location / { proxy_pass http://backend;
# This health check might not work...
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# Extract the 'Host' header from the request
proxy_set_header Host $host;
}一种可行的解决方案是创建一个虚拟的location块,在其中以静态方式定义健康检查事务使用的所有参数:
location /internal-health-check1 { internal; # Prevent external requests from matching this location block
proxy_pass http://backend;
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# Explicitly set request parameters; don't use run-time variables
proxy_set_header Host www.example.com;
}有关更多信息,请参阅《NGINX Plus 管理指南》。
会话持久性
借助会话持久性,无法以集群方式部署的应用也能可靠地实现负载均衡和扩展。存储和复制会话状态的应用可以更高效地运行,并提升最终用户体验。
某些应用有时会将状态信息存储在上游服务器上,例如,当用户将商品放入虚拟购物车或编辑已上传的图像时。在这些情况下,您可能希望将该用户后续的所有请求都定向到同一台服务器。
会话持久性指定请求必须路由到的服务器,而负载均衡则允许NGINX选择合适的上游服务器。借助NGINX Plus的会话持久性功能,这两个过程可以同时运行:
如果请求与会话持久性规则匹配
则使用目标上游服务器
否则应用负载均衡算法选择上游服务器
如果目标服务器不可用,导致会话持久性决策失败,NGINX Plus将进行负载均衡决策。
最简单的会话持久性方法是“粘性 Cookie”方法。NGINX Plus 会在首次响应中插入一个 Cookie,用于标识粘性上游服务器:
sticky cookie srv_id expires=1h domain=.example.com path=/;在另一种“粘性路由”方法中,NGINX会根据JSESSIONID Cookie等请求参数选择上游服务器:
upstream backend {
server backend1.example.com route=a;
server backend2.example.com route=b;
# select first non-empty variable; it should contain either 'a' or 'b'
sticky route $route_cookie $route_uri;
}有关更多信息,请参阅《NGINX Plus 管理指南》。
重写HTTP重定向
如果某些重定向失效,请重写HTTP重定向;尤其是在发现请求从代理被重定向到实际的上游服务器时。
代理到上游服务器时,服务器会在本地地址上发布应用,但您会通过另一个地址(即代理地址)访问该应用。这些地址通常会解析为域名;如果服务器和代理使用不同的域名,可能会出现问题。
例如,在测试环境中,可以直接通过IP地址访问代理,也可以使用“localhost”访问。但是,上游服务器可能会侦听实际域名(例如“www.nginx.com”)。当上游服务器发出重定向消息时(使用“3xx”状态码和“Location”标头,或使用“Refresh”标头),该消息中可能包含服务器的实际域名。
NGINX会尝试拦截并纠正此问题中最常见的情况。如果需要完全控制并强制执行特定重写,请按如下方式使用proxy_redirect指令:
proxy_redirect http://staging.mysite.com/ http://$host/;重写HTTP响应
有时需要重写HTTP响应中的内容。例如,在上述示例中,响应可能包含指向代理服务器以外其他服务器的绝对链接。
可以使用sub_filter指令定义要应用的重写规则:
sub_filter /blog/ /blog-staging/;
sub_filter_once off;一个很常见的注意事项是HTTP压缩的使用。如果客户端表明可以接受压缩数据,服务器随后压缩响应,NGINX将无法检查和修改该响应。最简单的解决方法是将客户端请求中的Accept-Encoding标头设置为空字符串(""),从而将其移除:
proxy_set_header Accept-Encoding "";完整示例
以下负载均衡配置模板采用了本文讨论的所有技术。NGINX Plus提供的高级功能以橙色突出显示。
[编辑注:以下配置已更新为使用NGINX Plus API进行实时活动监控和上游组动态配置,取代了最初使用的独立模块。]
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Accept-Encoding "";
proxy_redirect http://staging.example.com/ http://$host/;
# Rewrite the Host header to the value in the client request
proxy_set_header Host $host;
# Replace any references inline to staging.example.com
sub_filter http://staging.example.com/ /;
sub_filter_once off;
}
location /internal-health-check1 {
internal; # Prevent external requests from matching this location block
proxy_pass http://backend;
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# Explicitly set request parameters; don't use runtime variables
proxy_set_header Host www.example.com;
}
upstream backend {
zone backend 64k; # Use NGINX Plus' shared memory
least_conn;
keepalive 20;
# Apply session persistence for this upstream group
sticky cookie srv_id expires=1h domain=.example.com path=/servlet;
server webserver1 weight=1;
server webserver2 weight=4;
}
match statusok {
# Used for /test.php health check
status 200;
header Content-Type = text/html;
body ~ "Server[0-9]+ is alive";
}
server {
listen 8080;
root /usr/share/nginx/html;
location = /api {
api write=on; # Live activity monitoring and
# dynamic configuration of upstream groups
allow 127.0.0.1; # permit access from localhost
deny all; # deny access from everywhere else
}
}亲自体验NGINX Plus丰富的负载均衡功能,立即开始30天免费试用,或联系我们,探讨您的用例。
关于作者

相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
