当前位置: 首页 > news >正文

动态可写的四层路由利器ngx_stream_keyval_module

1.模块价值概述

传统 Stream 反向代理想要按域名 / IP / 前缀做动态转发,通常需要:

  • 修改 nginx.conf → reload
  • 借助外部配置中心或自研 Lua 共享字典
    这在 大规模集群服务动态上下线 场景下并不优雅。

ngx_stream_keyval_module 通过 API 可写的 Key-Value 数据库 + $variable 动态查询,让我们在 不 reload、秒级生效 的前提下完成四层路由、灰度、熔断等操作。

2.核心概念

概念说明
keyval_zone定义一块共享内存(zone)存放 K-V 数据;可持久化到 JSON 文件
keyval声明「用某个 key 查询 zone,结果赋给 $variable」的语义
API/api/6/http/keyvals/<zone>(HTTP 块开启 api write=on);支持 PUT/GET/DELETE
type指定匹配规则:string 精确、ip 子网包含、prefix 前缀匹配
timeout / sync键值过期 & 多节点一致性(Nginx Plus Cluster / DNS 发现)

3.最小可运行示例

3.1 配置文件

# http 块开放 API
http {server {listen 8080;location /api {api write=on;          # 允许写操作}}
}# stream 块按 SNI 动态转发
stream {# ① 申请 32KB 共享内存;JSON 持久化到本地keyval_zone zone=sni2up:32k state=/var/lib/nginx/state/sni_up.keyval;# ② $ssl_server_name 查询 zone,结果写入 $upkeyval $ssl_server_name $up zone=sni2up;server {listen              443   ssl;ssl_certificate     /etc/nginx/cert.pem;ssl_certificate_key /etc/nginx/key.pem;proxy_pass          $up;  # 动态 upstream}
}

3.2 在线修改路由

# 新增 / 更新
curl -X PUT 'http://localhost:8080/api/6/http/keyvals/sni2up' \-d '{"a.example.com":"10.0.0.1:8443", "b.example.com":"10.0.0.2:9443"}'# 查询
curl http://localhost:8080/api/6/http/keyvals/sni2up# 删除条目
curl -X DELETE 'http://localhost:8080/api/6/http/keyvals/sni2up/b.example.com'

无需 nginx -s reload,客户端下一个 TLS 握手立即生效。

4.多种匹配模式

4.1 IP 子网匹配(type=ip)

keyval_zone zone=ip2dst:128k type=ip;
keyval $remote_addr $dst zone=ip2dst;server {listen 3306;proxy_pass $dst;   # 针对不同运营商或 VPC 子网分库
}
# 运营商 A 网段
{"203.0.113.0/24":"db-a.internal:3306"}
# 精确 IP
{"203.0.113.10/32":"db-vip.internal:3306"}

匹配原则:先找精确 IP,其次子网;同级取最先写入的键。

4.2 前缀匹配(type=prefix)

keyval_zone zone=pfx:64k type=prefix;
keyval $ssl_server_name $backend zone=pfx;
  • 写入 api. → 命中 api.foo.com
  • 写入 cdn. → 命中 cdn.img.foo.com

适合 多层子域 共用同一后端的场景。

5.过期与同步

场景设置行为
自动下线timeout=10m条目 10 分钟后失效并删除
集群一致timeout=10m sync仅在目标节点删除,其余节点等待超时淘汰;配合 DNS/RR 调度

注意:sync 需启用 Nginx Plus 进程集群通信(同一 Anycast VIP 或 DNS Service)。

6.结合 njs 实现自助写入

js_import kv.lua;              # 伪代码示例
keyval_zone zone=dyn:32k;
keyval $remote_addr $route zone=dyn;server {listen 2525;js_access kv.put_route;    # 在 access 阶段更新路由proxy_pass $route;
}

kv.put_route 里通过 $control 变量调用 API 或 ngx.fetch() 将新键写入 dyn,实现“客户端首次访问即注册目标”的自发现能力。

7.实战案例

场景玩法效益
动态 SNI 反向代理域名 → 内网 IP 的灰度、回滚SaaS 平台一键切流
数据库主从切换$remote_addr → 新主库可编排自动故障转移
封禁/优选 IPIPCIDR → deny/proxy_pass实时风控,0 reload
AB 灰度/蓝绿前缀匹配 Header支撑万级域名不改配置

8.最佳实践 & 踩坑提示

  1. 合理规划 zone 大小

    • 32 k ≈ 256 条左右键值;按平均键长估算,留 20% 冗余。
  2. 启用持久化

    • 防止 graceful restart 时丢失映射;JSON 文件由 Nginx 生成,不要人工编辑。
  3. 大量写操作

    • 并发 PUT 建议走 单独管理节点,业务节点只读;否则锁竞争可能增大延迟。
  4. 监控指标

    • Plus Dashboard / Prometheus 暴露 keyval_zone.capacityused,提早告警扩容。
  5. 跨机房同步

    • sync 只保证“最终一致”,不要依赖于亚秒级删除。

9.总结

ngx_stream_keyval_module 赋予了 Nginx Stream 网关 “分布式 KV + 热更新路由” 的能力:

  • API 驱动:告别 reload,秒级动态生效
  • 多种匹配:精确 / CIDR / 前缀 三套索引覆盖 80% 以上场景
  • 高可用:持久化 + 超时淘汰 + 节点同步,保障故障恢复
  • 弹性扩展:配合 njs/Lua 可自助注册,实现服务自发现、自愈

如果你的四层代理还在为 “配置变更慢、灰度困难、封禁繁琐” 而头疼,不妨升级到 Nginx Plus,并开启 ngx_stream_keyval_module,让 “Key 动态、Value 即路由” 成为日常运维的标配。

http://www.lqws.cn/news/211411.html

相关文章:

  • WSF07N10 MOSFET 在铲皮机中的应用
  • 【西门子杯工业嵌入式-3-如何使用KEY】
  • 垃圾回收相关八股
  • Redis内存淘汰策略
  • 【Linux】LInux下第一个程序:进度条
  • 东芝Toshiba e-STUDIO2110AC打印机信息
  • 数据结构算法(C语言)
  • Ctrl-Crash 助力交通安全:可控生成逼真车祸视频,防患于未然
  • 基于 Transformer robert的情感分类任务实践总结之二——R-Drop
  • altium designer2024绘制stm32过程笔记x`
  • WebRTC通话原理与入门难度实战指南
  • 从零开始制作小程序简单概述
  • Oracle 审计参数:AUDIT_TRAIL 和 AUDIT_SYS_OPERATIONS
  • SDC命令详解:使用set_port_fanout_number命令进行约束
  • AIGC的产品设计演进:从工具到协作者
  • 生成模型从自回归到变分自动编码器
  • 提供MD5解密的网站
  • WaytoAGI东京大会开启AI全球化新对话:技术无国界,合作促创新
  • 虚拟主机都有哪些应用场景?
  • C++11新增重要标准(下)
  • OTF字体包瘦身,保留想要的字
  • 【win | docker开启远程配置】使用 SSH 隧道访问 Docker的前操作
  • excel中数字不满六位在左侧前面补0的方法
  • python打卡第45天
  • 【自然语言处理】大模型时代的数据标注(主动学习)
  • 如何评估大语言模型效果
  • 机器学习-经典分类模型
  • 微前端 - Module Federation使用完整示例
  • Spring Boot + Thymeleaf 防重复提交
  • 算法练习-回溯