当前位置: 首页 > 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 即路由” 成为日常运维的标配。

相关文章:

  • c++算法学习6——记忆化搜索
  • 【推荐算法】推荐算法演进史:从协同过滤到深度强化学习
  • iview中的table组件点击一行中的任意一点选中本行
  • 王劲松《人民日报》撰文 重读抗战家书不忘来时路
  • 数据类型--实型
  • QT 第二讲 --- 基础篇 Qt的第一个程序
  • 【Go语言基础【12】】指针:声明、取地址、解引用
  • 【python】RGB to YUV and YUV to RGB
  • 隐私计算时代B端页面安全设计:数据脱敏与权限体系升级路径
  • RT-Thread内核组成——内核移植
  • 小白成长之路-Linux Shell脚本练习
  • Linux实战篇、第一章_02若依前后端部署之路(前端)
  • 谷歌Sign Gemma: AI手语翻译,沟通从此无界!
  • 快捷键的记录
  • python入门(2)
  • 使用 Laravel 中的自定义存根简化工作
  • 计算机组成原理-存储器的概述
  • 快速上手 Metabase:从安装到高级功能实战
  • 解决国产GD32下载的工程无法编译
  • 基于 GWAS 的群体遗传分析将 bZIP29 确定为玉米中的异种基因
  • 网站建设电话推广话术/合肥seo代理商
  • 郫县网站建设/百度快照优化的优势是什么
  • 厦门 外贸商城网站制作/成都网站seo厂家
  • 网站后台管理员扫描/铜陵seo
  • 南山老品牌网站建设/德芙巧克力软文推广
  • 广西网站建设营销公司/百度极速版推广