《NGINX 完全指南》章节精选 | 流量管理和可编程性
原文作者:Derek DeJonghe
原文链接:《NGINX 完全指南》章节精选 | 流量管理和可编程性
转载来源:NGINX 开源社区
NGINX 唯一中文官方社区 ,尽在 nginx.org.cn
编者按——由 O'Reilly 出版的《NGINX 完全指南》中文版(2022 年最新版)现已正式上线,现在点击即可免费下载电子版全本。
这本 180 多页易于理解的配置指南将为您讲述从如何安装 NGINX 到如何进行配置,再到如何调试和排除应用性能故障。不仅如此,本书还提供了将 NGINX 用于负载均衡、云部署、自动化、容器和微服务、服务网格、安全防护等场景的相关配置示例。
本文中,本书的中文校译熊平为大家节选了本书的第三章《流量管理》和第五章《可编程性和自动化》中的精彩段落:A/B 测试、限制速率、使用通用编程语言扩展 NGINX。
A/B 测试
问题
在文件或应用的两个或多个版本之间分割客户端流量,以测试接受度或参与度。
解决方案
使用 split_clients 模块将一定比例的客户端流量定向到一个不同的上游 (upstream) 池:
split_clients 指令对作为第一个参数提供的字符串进行哈希处理,并用该哈希值除以提供的百分比,以映射作为第二个参数提供的变量的值。在第一个参数中添加“AAA”是为了证明这是一个可以包含多个变量的串联字符串,如通用哈希负载均衡算法中所述。
第三个参数是一个包含键值 (key-value) 对的对象,其中键是百分比权重,值是要分配的值。键可以是百分比或星号。星号表示取完所有百分比后的剩余部分。对于 $variant 变量的值,backendv2 为客户端 IP 地址流量的 20% ,
backendv1 为其余 80%。
在此示例中,backendv1 和 backendv2 表示上游服务器池,可以与 proxy_pass 指令一起使用,如下所示:
使用变量 $variant 时,我们的流量将会分配给两个不同的应用服务器池。
为了理解 split_clients 的广泛用途,我们通过一个例子来看看两个静态站点版本之间的流量分割:
详解
在测试电子商务网站上不同类型的营销和前端功能的转化率时,这种类型的 A/B 测试非常有用。应用通常通过“灰度发布”进行部署。在这种类型的部署中,用户可以逐步增加路由到新版本的用户百分比,进而将流量慢慢切换到新版本。在推出新版本的代码时,在不同的应用版本之间分割客户端流量非常实用,这可以降低发生错误后带来的影响。
更常见的部署模式是蓝绿部署,也就说在将用户切换到新版本的同时,仍然保持旧版本在验证部署期间的可用性。无论出于何种原因在两组不同的应用之间分割客户端流量,NGINX 的 split_client 模块都可以帮您轻松搞定。
限制速率
问题
通过预定义的键(例如客户端的 IP 地址)来限制请求的速率。
解决方案
利用限速模块限制请求速率:
此示例配置创建了一个名为 limitbyaddr 的共享内存区。使用的预定义键是二进制形式的客户端 IP 地址。共享内存区的大小设置为 10 MB。该区域使用关键字参数设置速率。limit_req 指令使用了一个必不可少的关键字参数:zone。
zone 指示了要使用哪个共享内存请求限制区的指令。根据 limit_req_status 指令的定义,超过明示速率的请求将返回 429 HTTP 代码。建议设置一个 400 级范围的状态码,因为默认值是 503,这代表服务器有问题,而实际问题是出在客户端方面。
使用 limit_req 指令的可选关键字参数来启用两级速率限制:
在某些情况下,客户端需要同时发出许多请求,此后先在一段时间内降低速率,然后再发出更多请求。您可以使用关键字参数 burst 允许客户端超过其速率限制但不拒绝其请求。超出速率的请求将延迟处理,以将速率限制匹配到配置的值。
有一组关键字参数可以改变这种行为,即 delay 和 nodelay。nodelay 参数不带值,只允许客户端一次性消耗所有流量突发值;但是必须要先等待足够的时间,直到满足速率限制要求为止,否则所有请求都会被拒绝。
在此示例中,如果我们使用 nodelay,客户端可以在第一秒消耗 12 个请求,但是必须要在初始请求之后等待 4 秒才能发出另一个请求。delay 关键字参数定义了在不限流的情况下可以预先发出多少请求。在这种情况下,客户端可以毫无延迟地预先发出 9 个请求,接下来的 3 个将受到限制,此后 4 秒内的任何请求都将被拒绝。
详解
限速模块非常强大,可以防止滥用快速请求,同时仍然为每个人提供优质服务。限制请求速率的原因有很多,安全性就是其中之一。您可以通过严格限制登录页面的速率来防御暴力破解攻击。您可以对所有请求设置合理的限制,从而防止恶意用户试图对您的应用拒绝服务或浪费资源的不轨行为。
限速模块的配置很像连接限制模块,并且存在许多相同的问题。您可以按照每秒限速,也可以按照每分钟限速。当达到速率限制时,日志就会记录事件。
此外,还有一条指令没有在示例中给出:limit_req_log_level,它的默认值为 error,您也可以把它设置为 info、
notice 或 warn。在 NGINX Plus 中,速率限制目前具有集群感知能力。
测试限制可能是个很棘手的问题,测试方案通常很难在替代环境中模拟实时流量。在这种情况下,您可以将
limit_req_dry_run 指令设置为 on,然后使用访问日志中的变量 $limit_req_status。$limit_req_status 变量将计算为 PASSED、REJECTED 或 REJECTED_DRY_RUN。
启用 dry run 后,您将能够分析实时流量日志,并在真正实施限制前根据需要调整限制,从而确保您的限制配置正确。
使用通用编程语言扩展 NGINX
问题
您需要 NGINX 使用通用编程语言执行一些自定义扩展。
解决方案
在用 C 语言编写自定义 NGINX 模块之前,请先评估您的用例是否适合使用其他编程语言模块。C 编程语言是一种非常强大且高效的语言,但是也有许多其他语言模块能够支持所需的自定义。
NGINX 引入了 NGINX JavaScript (NJS),只需启用一个模块就可以将 JavaScript 的强大功能暴露到 NGINX 配置中。您也可以使用 Lua 和 Perl 模块。
使用这些语言模块时,您要么需要导入一个包含代码的文件,要么直接在配置中定义代码块。
要使用 Lua,请安装 Lua 模块和以下 NGINX 配置,以定义一个内联的 Lua 脚本:
Lua 模块通过 ngx 模块定义的对象提供自己的 NGINX API。与 NJS 中的 request 对象一样,ngx 对象也有描述请求和操作响应的属性和方法。
安装了 Perl 模块后,此示例将使用 Perl 从运行时环境设置 NGINX 变量:
上述示例表明,这些语言模块不仅仅是返回响应,而且还会暴露更多功能。perl_set 指令将一个 NGINX 变量设置为从 Perl 脚本返回的数据。这个示例比较有限,只是返回了用作请求代理端点的系统环境变量。
详解
NGINX 具备出色的可扩展性,这为启用更多功能开创了更多可能。NGINX 可通过使用 C 语言模块自定义代码来扩展,您可以从一开始构建时就把这些模块编译到 NGINX 中,也可以在配置中动态加载。
目前还有一些模块可以暴露 JavaScript (njs)、Lua 和 Perl 的功能与语法。在多数情况下这些预先存在的模块是够用的 —— 除非将 NGINX 的自定义功能分配出去。现在开源社区中有很多为这些模块构建的脚本。
该解决方案演示了 NGINX 和 NGINX Plus 中可用的 Lua 和 Perl 脚本语言的基本用法。无论是寻求响应、设置变量、发送子请求还是定义复杂的重写,这些 NGINX 模块都能提供相应的支持。
本节中文版校译
熊平
F5 NGINX 资深架构师
拥有超过 20 年应用交付领域工作经验。拥有 F5 认证方案专家、NGINX 认证教练、CKA、亚马逊云科技架构师以及 TOGAF 等多项行业认证,对微服务架构、应用高可用、应用优化和安全防护有着独特的见解,以及深厚的积累。
NGINX 唯一中文官方社区 ,尽在 nginx.org.cn
评论