如何实现动态黑名单实时下发而不需重新加载配置文件?
- 内容介绍
- 文章标签
- 相关推荐
本文共计787个文字,预计阅读时间需要4分钟。
动态
用 OpenResty + Redis 实现毫秒级生效
这是目前最成熟、低侵入、高可用的方案。Nginx 本身不 reload,所有黑白名单状态都存在 Redis 中,Lua 脚本每次请求时实时查询:
- 在
http块用init_by_lua_block初始化 Redis 连接池,复用连接,避免性能损耗 - 在
location或server块中用access_by_lua_block获取客户端真实 IP(优先读X-Real-IP或X-Forwarded-For),再查GET blacklist:1.2.3.4 - 命中则直接
ngx.exit(403),未命中继续代理;整个过程耗时通常低于 5ms - 封禁操作只需一条命令:
redis-cli SETEX "blacklist:1.2.3.4" 7200 "1",TTL 到期自动清理,零运维干预
用 Nacos 配置中心做规则托管(适合 Java 生态)
如果系统已接入 Nacos,可将 IP 黑名单以 JSON 格式存为配置项(例如 gateway.blacklist = ["192.168.1.100", "203.0.113.5"]),后端网关或过滤器监听变更:
- 服务启动时拉取一次,后续通过长轮询或事件通知(如 Nacos SDK 的
addListener)感知配置更新 - 收到新配置后,将数组加载进本地
ConcurrentHashMap或布隆过滤器,避免每次请求都远程调用 - 相比 Redis 方案,它更利于审计和版本回溯,但下发延迟略高(秒级),且依赖 SDK 稳定性
- 适合黑白名单变动不频繁(每小时至每天)、需与业务配置统一管理的场景
为什么不能只靠 nginx.conf 的 deny?
原生 deny 1.2.3.4; 写死在配置里,每次增删都必须执行 nginx -s reload。这看似简单,实则带来三个硬伤:
- reload 会创建新 worker 进程,旧进程 graceful shutdown 期间仍处理请求,导致新旧规则并存,出现“漏放”或“误杀”
- 高频 reload(如每分钟多次)易引发 worker 进程堆积、内存泄漏,长期运行后稳定性下降
- 无法支持 TTL、来源标记、自动解封等增强能力,纯静态,运维成本随规模指数上升
真实部署建议
生产环境推荐组合使用:Redis 承担实时拦截(快),Nacos 承担规则备案与批量管理(稳)。例如,安全平台调用管理接口封禁 IP 时,同时写 Redis(立即生效)和 Nacos(持久记录),后续定时任务可将 Nacos 中的长期封禁同步到 Redis 并设长 TTL。
这样既保证了响应速度,又保留了配置可追溯、可灰度、可回滚的能力。
本文共计787个文字,预计阅读时间需要4分钟。
动态
用 OpenResty + Redis 实现毫秒级生效
这是目前最成熟、低侵入、高可用的方案。Nginx 本身不 reload,所有黑白名单状态都存在 Redis 中,Lua 脚本每次请求时实时查询:
- 在
http块用init_by_lua_block初始化 Redis 连接池,复用连接,避免性能损耗 - 在
location或server块中用access_by_lua_block获取客户端真实 IP(优先读X-Real-IP或X-Forwarded-For),再查GET blacklist:1.2.3.4 - 命中则直接
ngx.exit(403),未命中继续代理;整个过程耗时通常低于 5ms - 封禁操作只需一条命令:
redis-cli SETEX "blacklist:1.2.3.4" 7200 "1",TTL 到期自动清理,零运维干预
用 Nacos 配置中心做规则托管(适合 Java 生态)
如果系统已接入 Nacos,可将 IP 黑名单以 JSON 格式存为配置项(例如 gateway.blacklist = ["192.168.1.100", "203.0.113.5"]),后端网关或过滤器监听变更:
- 服务启动时拉取一次,后续通过长轮询或事件通知(如 Nacos SDK 的
addListener)感知配置更新 - 收到新配置后,将数组加载进本地
ConcurrentHashMap或布隆过滤器,避免每次请求都远程调用 - 相比 Redis 方案,它更利于审计和版本回溯,但下发延迟略高(秒级),且依赖 SDK 稳定性
- 适合黑白名单变动不频繁(每小时至每天)、需与业务配置统一管理的场景
为什么不能只靠 nginx.conf 的 deny?
原生 deny 1.2.3.4; 写死在配置里,每次增删都必须执行 nginx -s reload。这看似简单,实则带来三个硬伤:
- reload 会创建新 worker 进程,旧进程 graceful shutdown 期间仍处理请求,导致新旧规则并存,出现“漏放”或“误杀”
- 高频 reload(如每分钟多次)易引发 worker 进程堆积、内存泄漏,长期运行后稳定性下降
- 无法支持 TTL、来源标记、自动解封等增强能力,纯静态,运维成本随规模指数上升
真实部署建议
生产环境推荐组合使用:Redis 承担实时拦截(快),Nacos 承担规则备案与批量管理(稳)。例如,安全平台调用管理接口封禁 IP 时,同时写 Redis(立即生效)和 Nacos(持久记录),后续定时任务可将 Nacos 中的长期封禁同步到 Redis 并设长 TTL。
这样既保证了响应速度,又保留了配置可追溯、可灰度、可回滚的能力。

