多地区家宽节点统一管理,代理池统一调度Redis中心化
多地区家宽节点统一管理,本质上要解决三件事:节点分布在不同的家庭宽带下、出口 IP 随时可能变化、部分节点会因为断网或运营商限制离线。
代理池统一调度如果只靠配置文件或数据库轮询,往往会出现调度到失效节点、可用率低的问题。
用 Redis 作为中心化调度核心,可以在一套轻量结构里同时维护节点心跳、权重和可用状态。
下面这段内容适合已经持有多个家宽节点、想自己搭调度系统的用户,不依赖第三方面板,读完可以直接照做。
为什么家宽节点调度适合交给 Redis
家庭宽带节点与机房服务器最大的不同是稳定性。
节点 IP 可能不是固定的,线路延迟也会随着时间段变化。
代理池调度需要快速判断哪个节点当前可用、哪个节点近期成功率低,然后分配任务。
Redis 的几个特性刚好匹配这类场景:
- 内存读取快,调度时不用反复查数据库。
ZSET可以按分数存节点权重或可用性评分,天然适合排序分配。Hash能保存节点详情、最近心跳时间、累计失败次数。EXPIRE可以自动清理掉长时间没有上报心跳的节点。
动手前需要准备什么
在写调度逻辑前,建议先确认环境可用:
- 一台所有节点都能访问到的主控服务器,Redis 安装在这台机器上。
- 每个家宽节点上至少能运行一个心跳上报脚本,语言不限,能发 HTTP 请求或直接执行
redis-cli即可。 - Redis 建议使用 5.0 以上版本,方便使用 Stream 等扩展能力。当前方案只用基础命令,版本影响不大。
主控服务器注意放行 Redis 端口。
实际生产环境不要让 Redis 直接暴露公网,建议通过内网、VPN 或带认证的隧道连接。
用 Redis 实现中心化调度的核心步骤
这一套实现不依赖复杂框架,把节点注册、心跳上报、负载分配和故障剔除做好,就能运行。
第一步:节点上线后先注册自己
每个节点连接主控 Redis 后,写入自己的唯一标识和基本信息。
例如节点编号是 node-js-01,地区是江苏:
redis-cli -h 主控IP -a 密码 HSET proxy:node:node-js-01 region jiangsu ip 180.100.10.10
redis-cli -h 主控IP -a 密码 HSET proxy:node:node-js-01 status ready
redis-cli -h 主控IP -a 密码 EXPIRE proxy:node:node-js-01 180
使用 EXPIRE 给节点信息加 180 秒过期时间,就是为了防止离线节点长期残留在调度列表里。
第二步:心跳上报刷新可用状态
节点端建议每 30 秒执行一次心跳。
心跳要做两件事:更新节点 Hash 里的最近活跃时间,同时把节点 ID 加入一个排在 ZSET 里的调度池。
redis-cli -h 主控IP -a 密码 HSET proxy:node:node-js-01 last_seen $(date +%s)
redis-cli -h 主控IP -a 密码 EXPIRE proxy:node:node-js-01 180
redis-cli -h 主控IP -a 密码 ZADD proxy:pool:ready 100 node-js-01
这里 ZADD 的分数用 100 表示默认权重。
如果节点带宽大、延迟低,可以把分数调低,调度时会优先取分数小的节点。
第三步:中心调度从就绪池里取节点
一段简单的调度逻辑通常这样工作:
# 弹出分数最低的节点 ID
redis-cli -h 主控IP -a 密码 ZPOPMIN proxy:pool:ready 1
拿到节点 ID 后,再从 Hash 里读取连接详情,然后把任务交给这个节点。
节点被取出后不要立刻删掉,建议先在 Redis 里放入一个临时锁或状态标记,等任务完成后再归还到就绪池。
第四步:失败自动归还或剔除
如果节点执行任务失败,可以在节点 Hash 中累加失败次数:
redis-cli -h 主控IP -a 密码 HINCRBY proxy:node:node-js-01 fail_count 1
预设一个阈值,比如连续失败 3 次,就把这个节点从 ZSET 里移除:
redis-cli -h 主控IP -a 密码 ZREM proxy:pool:ready node-js-01
这种方式能避免代理池均匀把请求分给一个已经失效的家宽节点。
一段时间后验证调度是否可靠
接入几个不同地区的节点后,不要只看界面状态,建议用下面的方法验证:
- 查看 Node 的
ready节点数:redis-cli -h 主控IP -a 密码 ZCARD proxy:pool:ready,数量应该等于正常节点数。 - 手动停掉一个节点的上报脚本,等待超过 180 秒后检查 Hash 是否自动消失,ZSET 里是否还被移除。这能验证过期和清理逻辑。
- 连续调度 100 次任务,统计分配到每个节点的次数是否符合预设计权重。如果某个节点一直没被分配到,先检查它的分数和状态。
容易踩的几个坑
这套方案踩坑点通常不在 Redis 本身,而在于节点上报设计:
- 节点时间不一致导致心跳过期判断错乱。各节点建议统一安装 NTP 时间同步,否则
timestamp会误导排查。 - 节点只上报自身存活,没有上报出口 IP 变化。家宽节点的出口 IP 经常变,建议节点每次心跳时重新获取当前出口 IP 并更新到 Hash 中。
- 调度取走节点后没有及时放回。
ZPOPMIN会移除节点,如果任务执行慢,其他线程就调度不到这个节点。可以结合租约时间,任务结束再归还,不要无脑删。 - Redis 无认证暴露公网。尽量避免,必须暴露时启用
requirepass、绑定访问 IP,并定期检查有没有被恶意写入。
如果你正准备把分散在多个地区的家宽节点纳进同一个代理池,先按上面的 Redis 数据结构跑通最小闭环,再根据实际节点数量增加超时重试、动态评分和操作记录。
初期不需要一上来就设计复杂的调度算法,把节点状态和心跳链路管好,调度中心的扩展就有稳定基础。
遇到问题时优先检查心跳是否还在刷新、过期时间是否设置正确、ZSET 里的分数是否符合预期,多数异常都能快速定位。