在使用 NGINX 和 NGINX Plus 实现负载平衡(第 1 部分)中,我们设置了一个简单的 HTTP 代理来在多个 Web 服务器之间实现流量负载平衡。 在本文中,我们将介绍NGINX Plus中的其他功能:使用keepalives进行性能优化、健康检查、会话持久性、重定向和内容重写。
有关 NGINX 和 NGINX Plus 中负载平衡功能的详细信息,请参阅NGINX Plus 管理指南。
编辑器 – NGINX Plus Release 5及更高版本还可以对基于TCP的应用进行负载均衡。 在第 6 版中,通过增加健康检查、动态重新配置、SSL 终止等功能,TCP 负载均衡得到了显著扩展。 在 NGINX Plus Release 7及更高版本中,TCP 负载均衡器具有与 HTTP 负载均衡器完全相同的功能。 版本 9 中引入了对UDP 负载均衡的支持。
您可以在流
上下文而不是http
上下文中配置 TCP 和 UDP 负载均衡。 由于 HTTP 和 TCP/UDP 之间固有的差异,可用的指令和参数略有不同;有关详细信息,请参阅HTTP和TCP/UDP上游模块的文档。
回顾一下,这是我们在上一篇文章中构建的配置:
server { listen 80;
location / {
proxy_pass http://backend;
# 将“Host”标头重写为客户端请求中的值,
# 或主服务器名称
proxy_set_header Host $host;
# 或者,将值放入配置中:
# proxy_set_header Host www.example.com;
}
}
upstream backend {
zone backend 64k; # 使用 NGINX Plus 的共享内存
least_conn;
server webserver1 weight=1;
server webserver2 weight=4;
}
在本文中,我们将介绍一些配置 NGINX 和 NGINX Plus 的简单方法,以提高负载均衡的有效性。
在 NGINX 或 NGINX Plus 与上游服务器之间启用 HTTP 保持连接可提高性能(通过减少延迟)并降低 NGINX 耗尽临时端口的可能性。
HTTP 协议使用底层 TCP 连接来传输 HTTP 请求和接收 HTTP 响应。 HTTP 保持活动连接允许重用这些 TCP 连接,从而避免了为每个请求创建和销毁连接的开销:
NGINX 是一个完整的代理,它独立管理来自客户端的连接(前端保持连接)和到服务器的连接(上游保持连接):
NGINX 维护一个保持活动连接的“缓存”,即一组到上游服务器的空闲保持活动连接,当它需要将请求转发到上游时,它使用缓存中已经建立的保持活动连接,而不是创建新的 TCP 连接。 这减少了 NGINX 与上游服务器之间的交易延迟,并降低了临时端口的使用率,因此 NGINX 能够吸收和负载平衡大量流量。 当流量激增时,缓存会被清空,在这种情况下 NGINX 会与上游服务器建立新的 HTTP 连接。
对于其他负载平衡工具来说,这种技术有时被称为多路复用、连接池、连接重用或OneConnect 。
您可以通过在配置中包含proxy_http_version
, proxy_set_header
和keepalive
指令来配置保持连接缓存:
服务器 { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1 ; proxy_set_header Connection "" ; } } 上游后端 { 服务器 webserver1; 服务器 webserver2; # 维持与上游服务器组最多 20 个空闲连接keepalive 20 ; }
启用健康检查可以提高负载平衡服务的可靠性,降低最终用户看到错误消息的可能性,还可以促进常见的维护操作。
NGINX Plus 中的健康检查功能可用于检测上游服务器的故障。 NGINX Plus 使用“合成事务”探测每台服务器,并根据您在health_check
指令上配置的参数检查响应(当您包含match
参数时,还会检查相关的match
配置块):
server { listen 80; location / { proxy_pass http://backend; health_check interval=2s tries to connect to the server that has been checked; health_check interval=2s tries to connect to the server that has been checked; health_check interval=2s tries to connect to the server that has been checked ; health_check interval=2s tries to connect to the server that has been checked; health_check interval=2s tries to connect to the server that has been checked; health_check interval = 2s .
健康检查从其父位置
块继承一些参数。 如果您在配置中使用运行时变量,这可能会导致问题。 例如,以下配置适用于实际 HTTP 流量,因为它从客户端请求中提取Host
标头的值。 它可能不适用于健康检查使用的合成事务,因为没有为它们设置Host
标头,这意味着合成事务中不使用Host
标头。
location / { proxy_pass http://backend;
# 此健康检查可能不起作用...
health_check interval=2s tries=1 through=5 uri=/test.php match=statusok;
# 从请求中提取“Host”标头
proxy_set_header Host $host;
}
一个好的解决方案是创建一个虚拟位置
块,静态定义健康检查事务使用的所有参数:
location /internal-health-check1 { internal; # 防止外部请求匹配此位置块
proxy_pass http://backend;
health_check interval=2s tries=1 tries=5 uri=/test.php match=statusok;
# 明确设置请求参数;不要使用运行时变量
proxy_set_header Host www.example.com;
}
欲了解更多信息,请参阅NGINX Plus 管理指南。
通过会话持久性,无法部署在集群中的应用可以实现负载平衡并可靠地扩展。 存储和复制会话状态的应用运行更高效,最终用户的性能也得到了提高。
某些应用有时会将状态信息存储在上游服务器上,例如当用户将商品放入虚拟购物车或编辑上传的图像时。 在这些情况下,您可能希望将该用户的所有后续请求定向到同一台服务器。
会话持久性指定了请求必须路由到的位置,而负载均衡使 NGINX 可以自由选择最佳上游服务器。 这两个进程可以使用 NGINX Plus 的会话持久功能共存:
如果请求与会话持久规则匹配
然后使用目标上游服务器
否则应用负载平衡算法来选择上游服务器
如果会话持久性决策由于目标服务器不可用而失败,则 NGINX Plus 将做出负载平衡决策。
最简单的会话持久性方法是“粘性 cookie ”方法,其中 NGINX Plus 在第一个响应中插入一个 cookie,用于标识粘性上游服务器:
粘性 cookie srv_id 过期=1h domain=.example.com path=/;
在替代的“粘性路由”方法中,NGINX 根据请求参数(例如 JSESSIONID cookie)选择上游服务器:
上游后端 { server backend1.example.com route=a ; server backend2.example.com route=b ; # 选择第一个非空变量;它应该包含“a”或“b”粘性路由 $route_cookie $route_uri ; }
欲了解更多信息,请参阅NGINX Plus 管理指南。
如果某些重定向被破坏,请重写 HTTP 重定向,特别是当您发现自己从代理重定向到真正的上游服务器时。
当您代理到上游服务器时,服务器会在本地地址上发布应用,但您通过不同的地址(代理的地址)访问该应用。 这些地址通常解析为域名,如果服务器和代理有不同的域,则可能会出现问题。
例如,在测试环境中,您可以直接(通过 IP 地址)或将代理寻址为localhost 。 但是,上游服务器可能会监听真实的域名(例如www.nginx.com )。 当上游服务器发出重定向消息(使用3xx
状态和Location
标头,或使用Refresh
标头)时,该消息可能包含服务器的真实域。
NGINX 尝试拦截并纠正此问题的最常见实例。 如果您需要完全控制来强制特定重写,请使用proxy_redirect
指令,如下所示:
代理重定向 http://staging.mysite.com/ http://$host/;
有时您需要重写 HTTP 响应中的内容。 也许,如上面的例子一样,响应包含指向代理以外的服务器的绝对链接。
您可以使用sub_filter
指令来定义要应用的重写:
sub_filter /blog/ /blog-staging/;
sub_filter_once 关闭;
一个非常常见的陷阱是使用 HTTP 压缩。 如果客户端表示它可以接受压缩数据,然后服务器压缩响应,则 NGINX 无法检查和修改响应。 最简单的措施是从客户端请求中删除Accept-Encoding
标头,方法是将其设置为空字符串( “”
):
proxy_set_header 接受编码“”;
这是负载平衡配置的模板,它采用了本文讨论的所有技术。 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/; # 将 Host 标头重写为客户端请求中的值 proxy_set_header Host $host; # 替换对 staging.example.com 的任何内联引用 sub_filter http://staging.example.com/ /; sub_filter_once off; } location /internal-health-check1 { internal; # 防止外部请求匹配此位置 block proxy_pass http://backend; health_check interval=2s tries to match this location block proxy_pass http://backend; health_check interval=2s tries to match this location block proxy_set_header host www.example.com; } upper backend { zone backend 64k ; # 使用 NGINX Plus 的共享内存 least_conn; keepalive 20; # 为此上游组应用会话持久性粘性 cookie srv_id expires=1h domain=.example.com path=/servlet ; 服务器 webserver1 weight=1; 服务器 webserver2 weight=4; } match statusok { # 用于 /test.php 健康检查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 ; #实时活动监控和 #上游组的动态配置allow 127.0.0.1; # 允许从本地主机访问 denied all; # 拒绝从其他地方访问 } }
亲自尝试 NGINX Plus 中所有出色的负载平衡功能 - 立即开始30 天免费试用或联系我们讨论您的用例。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”