博客 | NGINX

使用 NGINX 和 NGINX Plus 进行负载平衡(第 2 部分)

NGINX-F5-horiz-black-type-RGB 的一部分
欧文·加勒特缩略图
欧文·加勒特
2014 年 3 月 17 日发布

使用 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 之间固有的差异,可用的指令和参数略有不同;有关详细信息,请参阅HTTPTCP/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 的简单方法,以提高负载均衡的有效性。

HTTP 保持连接

在 NGINX 或 NGINX Plus 与上游服务器之间启用 HTTP 保持连接可提高性能(通过减少延迟)并降低 NGINX 耗尽临时端口的可能性。

HTTP 协议使用底层 TCP 连接来传输 HTTP 请求和接收 HTTP 响应。 HTTP 保持活动连接允许重用这些 TCP 连接,从而避免了为每个请求创建和销毁连接的开销:

韓國

NGINX 是一个完整的代理,它独立管理来自客户端的连接(前端保持连接)和到服务器的连接(上游保持连接):

NGINX 维护一个保持活动连接的“缓存”,即一组到上游服务器的空闲保持活动连接,当它需要将请求转发到上游时,它使用缓存中已经建立的保持活动连接,而不是创建新的 TCP 连接。 这减少了 NGINX 与上游服务器之间的交易延迟,并降低了临时端口的使用率,因此 NGINX 能够吸收和负载平衡大量流量。 当流量激增时,缓存会被清空,在这种情况下 NGINX 会与上游服务器建立新的 HTTP 连接。

对于其他负载平衡工具来说,这种技术有时被称为多路复用连接池连接重用OneConnect

您可以通过在配置中包含proxy_http_versionproxy_set_headerkeepalive指令来配置保持连接缓存:

服务器 { 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 重定向

如果某些重定向被破坏,请重写 HTTP 重定向,特别是当您发现自己从代理重定向到真正的上游服务器时。

当您代理到上游服务器时,服务器会在本地地址上发布应用,但您通过不同的地址(代理的地址)访问该应用。 这些地址通常解析为域名,如果服务器和代理有不同的域,则可能会出现问题。

例如,在测试环境中,您可以直接(通过 IP 地址)或将代理寻址为localhost 。 但是,上游服务器可能会监听真实的域名(例如www.nginx.com )。 当上游服务器发出重定向消息(使用3xx状态和Location标头,或使用Refresh标头)时,该消息可能包含服务器的真实域。

NGINX 尝试拦截并纠正此问题的最常见实例。 如果您需要完全控制来强制特定重写,请使用proxy_redirect指令,如下所示:

代理重定向 http://staging.mysite.com/ http://$host/;

重写 HTTP 响应

有时您需要重写 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 内容。”