在使用 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;
# 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 的简单方法,以提高负载均衡的有效性。
在 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
指令来配置保持连接缓存:
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";
}
健康检查从其父位置
块继承一些参数。 如果您在配置中使用运行时变量,这可能会导致问题。 例如,以下配置适用于实际 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 /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 重定向,特别是当您发现自己从代理重定向到真正的上游服务器时。
当您代理到上游服务器时,服务器会在本地地址上发布应用,但您通过不同的地址(代理的地址)访问该应用。 这些地址通常解析为域名,如果服务器和代理有不同的域,则可能会出现问题。
例如,在测试环境中,您可以直接(通过 IP 地址)或将代理寻址为localhost 。 但是,上游服务器可能会监听真实的域名(例如www.nginx.com )。 当上游服务器发出重定向消息(使用3xx
状态和Location
标头,或使用Refresh
标头)时,该消息可能包含服务器的真实域。
NGINX 尝试拦截并纠正此问题的最常见实例。 如果您需要完全控制来强制特定重写,请使用proxy_redirect
指令,如下所示:
proxy_redirect http://staging.mysite.com/ http://$host/;
有时您需要重写 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 天免费试用或联系我们讨论您的用例。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”