原文作者:Owen Garrett - F5 产品管理高级总监
原文链接:使用 NGINX 和 NGINX Plus 实现负载均衡(第 2 部分)
转载来源:NGINX 中文官网
在《使用 NGINX 和 NGINX Plus 实现负载均衡(第 1 部分)》中,我们设置了一个简单的 HTTP 代理来跨多台 Web 服务器对流量进行负载均衡。本文将介绍 NGINX Plus 具备的一些其他功能:通过 keepalive、健康检查、会话保持、重定向及内容重写来优化性能。
编者按——NGINX Plus Release 5 及更高版本还可以对基于 TCP 的应用进行负载均衡。Release 6 通过增添健康检查、动态重新配置、SSL 终止等功能,显著扩展了 TCP 负载均衡。在 NGINX Plus Release 7 及更高版本中,TCP 负载均衡器具备与 HTTP 负载均衡器一样的功能。Release 9 中引入了对 UDP 负载均衡的支持。
您可以在 stream 上下文(而非 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 keepalive
在 NGINX 或 NGINX Plus 与上游服务器之间启用 HTTP keepalive 可提高性能(通过减少延迟),并降低 NGINX 耗尽临时端口的可能性。
HTTP 协议使用底层 TCP 连接来传输 HTTP 请求并接收 HTTP 响应。HTTP keepalive 连接允许重用这些 TCP 连接,从而避免了为每个请求创建和终止连接的开销:
NGINX 是一个全代理,可独立管理客户端连接(前端 keepalive 连接)和服务器连接(上游 keepalive 连接):
NGINX 会维护 keepalive 连接的“缓存”(一组与上游服务器的空闲 keepalive 连接),当需要将请求转发到上游服务器时,它会使用这些缓存中已建立的 keepalive 连接,而非创建新的 TCP 连接。
这可减少 NGINX 与上游服务器之间的事务延迟,并降低临时端口的使用率,因此 NGINX 能够处理大量流量并对其进行负载均衡。当流量激增时,这些缓存会被清空,在这种情况下,NGINX 将与上游服务器建立新的 HTTP 连接。
对于其他负载均衡工具,该技术有时称为“多路复用”、“连接池”、“连接复用”或“OneConnect”。
您可通过将 proxy_http_version、proxy_set_header 及 keepalive 指令添加到配置中来配置 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 自由选择最佳上游服务器。借助 NGINX Plus 的会话保持功能,这两个进程可以共存:
如果请求符合会话保持规则
那么使用目标上游服务器
否则应用负载均衡算法选择上游服务器
如果会话保持决策因目标服务器不可用而失败,那么 NGINX Plus 会做出负载均衡决策。
最简单的会话保持方法是“sticky cookie”方法,其中 NGINX Plus 在第一个响应中插入一个 cookie,用于标识 sticky 上游服务器:
sticky cookie srv_id expires=1h domain=.example.com path=/;
复制代码
在另一种“sticky 路由”方法中,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;
}
复制代码
重写 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 中所有出色的负载均衡功能,请点击此处阅读原文。
NGINX 唯一中文官方社区 ,尽在 nginx.org.cn
更多 NGINX 相关的技术干货、互动问答、系列课程、活动资源: 开源社区官网 | 微信公众号
评论