mirror of
https://gitcode.com/JianFeeeee/webui4frpc.git
synced 2026-10-15 12:14:37 +00:00
docs: README 补负载均衡(自导式释放)与集群页开关
## 新增 - **特性 → 集群模式**:负载均衡条目,点明**没有中心调度**及其原因。 - **运行 → 负载均衡参数**:`W4F_BALANCE_MODE` / `W4F_BALANCE_COOLDOWN` / `W4F_BALANCE_INTERVAL`,并写明集群页的开关**优先于**环境变量(页面上选过就以 页面为准,重启不丢)。 - **集群模式 → 新小节「负载均衡(自导式释放)」**:规则本体、四条边界 (自限到平摊值 / 不低于下限 / 不碰已停用转发 / **释放 ≠ 停止**)、三种模式、 只读报告的字段。 - **API 表**:`GET /cluster/balance`(read)、`POST /cluster/balance/mode`(write)。 - **架构 / 视图 / 测试**:补上负载均衡;并修正一处失效引用 `npm run type-check` → `npm run build`(web/package.json 的 scripts 里根本没有 type-check,照原文执行会报 missing script)。 ## 为什么这两个「为什么」要写进文档 1. **为什么只能自导**:负载信号是持有的转发数,而这个数只在**自己的拓扑条目消失** 时才下降,条目又是本地簿记 —— 所以 leader 只能*看见*失衡,无法*消除*它;要消除 就得伸手改另一个节点的簿记,而这正是这个环到处都在避免的跨节点写。 2. **为什么「释放」不能复用「停止」**:停止保留条目并标记链路停用;均衡释放必须 **删除条目**且保持链路启用。复用停止的话,每个节点的重复认领守卫都会拒绝这条 已是「有主」的转发,它会被永久搁死在刚放弃它的那台机器上。 这两条是设计约束而不是实现细节:后续任何人改这块,不知道原因就会改错。 ## 默认 dry-run 的理由也写明了 释放会停掉该转发的 frpc worker,其上的**在途连接会断一次**(新节点认领后恢复), 所以默认只报告不动作;模式开关走 write 级权限。 go test ./... 全绿(go clean -testcache 后)。
This commit is contained in:
71
README.md
71
README.md
@ -32,6 +32,14 @@
|
||||
- 主负载信号:当前节点拥有的转发数(权重 ×100)
|
||||
- 次级信号:**NIC 网络接口利用率**(从 `/proc/net/dev` 增量 + `/sys/class/net/*/speed` 计算,排除了 lo/docker/veth 等虚拟接口)
|
||||
- 同转发数节点间由内存占用 + 网络饱和度打破平局
|
||||
- **负载均衡(自导式)**:每个节点对**自己的**转发跑同一条规则 —— 持有数超过
|
||||
`ceil(总转发数 / 存活节点数)` 且至少 2 条时,自行撤销一条、把任务丢回环上,
|
||||
再由环按「最闲者优先」重新认领
|
||||
- **没有中心调度**:一节点的负载只有它自己的拓扑条目消失时才会下降,而条目是
|
||||
本地簿记,没有对端能代它写,所以只能由持有者自己动手
|
||||
- 规则自限:撤到平摊值即停(否则会把转发卸光),且低于下限永不撤、不会卸空节点
|
||||
- 每节点默认 10 分钟冷却,限制抖动频率;默认 **dry-run**(只报告不释放)
|
||||
- 集群页每节点一个开关:关闭 / 观察模式 / 启用,可持久化
|
||||
- **per-forward 独立进程**:每条转发拥有独立的 frpc 配置文件和 frpc 进程(worker 键 = `local~remote~port`),单条转发故障不影响兄弟,消除旧模型的多节点 `proxy already exists` 冲突
|
||||
- **容错自愈**:leader / 非 leader 节点宕机 → 自动检测 → 环跳过死亡节点、任务重挂;leader 宕机 → 上邻居晋升为新 leader
|
||||
- **宕机自动重联**:节点宕机重启后通过缓存的集群拓扑(对端地址 + 准入密钥)自动重联,显式脱离集群的节点不自动重联
|
||||
@ -160,6 +168,19 @@ sha256sum -c SHA256SUMS --ignore-missing
|
||||
|
||||
环境变量 `W4F_HOST` 可覆盖节点对外可达的主机名(Docker DNS / 通配监听场景用)。
|
||||
|
||||
### 负载均衡参数
|
||||
|
||||
每节点独立生效;集群页的开关**优先于**这里的默认值(在页面上选过就以页面为准,重启不丢)。
|
||||
|
||||
| 环境变量 | 默认 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `W4F_BALANCE_MODE` | `dry-run` | `off` 不参与 / `dry-run` 只报告 / `on` 真正释放 |
|
||||
| `W4F_BALANCE_COOLDOWN` | `600` | 同一节点两次释放之间的最小秒数 |
|
||||
| `W4F_BALANCE_INTERVAL` | `10` | 检查间隔(秒) |
|
||||
|
||||
**释放会停掉该转发的 frpc worker,其上的在途连接会断一次**,由新节点认领后恢复;
|
||||
因此默认是 `dry-run`。集群页的开关走 write 级权限。
|
||||
|
||||
### 启动行为
|
||||
|
||||
节点启动时的集群引导优先级:
|
||||
@ -191,10 +212,10 @@ webui4frpc(单二进制,无 frp 依赖,前端 go:embed)
|
||||
│ ├── render 渲染 frpc JSON 配置(per-forward 单 proxy + 高级参数 + LB/健康检查)
|
||||
│ ├── process worker 进程管理(spawn/stop/restart/自愈/日志轮转,worker 键 = local~remote~port)
|
||||
│ ├── install 一键下载官方 frpc(GitHub Releases,含解压安全防护)
|
||||
│ ├── cluster 令牌环协议(ring engine / leader 选举 / 容错 / 宕机重联 / 二进制分发 / NIC 负载采样)
|
||||
│ ├── cluster 令牌环协议(ring engine / leader 选举 / 容错 / 宕机重联 / 二进制分发 / NIC 负载采样 / 自导式负载均衡)
|
||||
│ └── httpapi REST API + 静态资源(auth/session / canvas / forwards / cluster / users / audit 导出)
|
||||
└── web/ Vue 3 SPA(Element Plus + VueFlow 画布 + Pinia)
|
||||
└── src/views/ 状态总览 / 连接配置(画布)/ 集群 / 设置 / 账号与密钥
|
||||
└── src/views/ 状态总览 / 连接配置(画布)/ 集群(含负载均衡开关)/ 设置 / 账号与密钥
|
||||
```
|
||||
|
||||
## API
|
||||
@ -220,6 +241,8 @@ webui4frpc(单二进制,无 frp 依赖,前端 go:embed)
|
||||
| | GET | `/binary/status` | read | frpc 路径 |
|
||||
| | POST | `/binary/install` | write | 安装 frpc |
|
||||
| **集群** | GET | `/cluster/ring` | read | 令牌环快照 |
|
||||
| | GET | `/cluster/balance` | read | 本节点负载均衡视图(只读,不变更状态) |
|
||||
| | POST | `/cluster/balance/mode` | write | 切换本节点负载均衡模式(持久化) |
|
||||
| | POST | `/cluster/create` | write | 创建独立集群 |
|
||||
| | POST | `/cluster/join-ring` | write | 加入集群(本节点发起) |
|
||||
| | POST | `/cluster/join` | write | 接收新节点加入 |
|
||||
@ -254,8 +277,45 @@ webui4frpc(单二进制,无 frp 依赖,前端 go:embed)
|
||||
- **任务分发**:在任意节点画布上配置 `localOnly=false` 的转发并保存 → 画布差异判断生成命令 → 令牌携带 → 负载最低节点摘取 → 拉起 frpc worker
|
||||
- **容错**:节点宕机 → 自动检测 → 环自愈(跳过死亡节点 / leader failover);重启 → 自动重联
|
||||
- **退出集群**:在集群页「退出集群」→ 本节点脱离为 standalone,不自动重联
|
||||
- **负载均衡**:见下节
|
||||
|
||||
集群页展示:环拓扑(self/leader 标记)、令牌轮次、节点负载、待办任务、活跃转发拓扑(含 owner 归属)、增量事件日志。
|
||||
集群页展示:环拓扑(self/leader 标记)、令牌轮次、节点负载、待办任务、活跃转发拓扑(含 owner 归属)、负载均衡(本机份额与释放计划)、增量事件日志。
|
||||
|
||||
### 负载均衡(自导式释放)
|
||||
|
||||
**为什么不是 leader 统一调度**:一节点的负载信号是它持有的转发数,而这个数只在
|
||||
**它自己的拓扑条目消失**时才下降 —— 条目是本地簿记。所以 leader 从外面只能*看见*
|
||||
失衡,无法*消除*它;要消除就得伸手改另一个节点的簿记,而这正是这个环到处都在避免
|
||||
的跨节点写(撤销、重启同样都是定向往 owner)。
|
||||
|
||||
于是规则由每个节点对自己的转发本地执行:
|
||||
|
||||
```
|
||||
当 持有转发数 >= 2 且 持有转发数 > ceil(总转发数 / 存活节点数)
|
||||
则 撤销其中一条 → 删除条目 → 以启用状态重新发布到环 → 由最闲节点认领
|
||||
```
|
||||
|
||||
- **自限**:撤到平摊值即停。3 条分 3 台时,持有 2 条的那台卸一条后变成 1 条,
|
||||
`1 > 1` 不成立 → 停手。没有这个上界,owner 会把转发全部卸光。
|
||||
- **不会卸空**:低于下限 2 条永不撤销。
|
||||
- **不碰已停用的转发**:停用条目的 entry 是用户「停用」决定的载体,释放它等于把
|
||||
一条**已停**的转发当活干交给别人。
|
||||
- **释放 ≠ 停止**:用户停止保留条目并标记链路为停用;均衡释放**删除条目**且链路保持
|
||||
启用。两者不能混用 —— 复用停止的话,每个节点的重复认领守卫都会拒绝这条已是「有主」
|
||||
的转发,它会被永久搁死在刚放弃它的那台机器上。
|
||||
|
||||
三种模式(集群页每节点一个开关,也可用 `W4F_BALANCE_MODE` 设默认值):
|
||||
|
||||
| 模式 | 行为 |
|
||||
| --- | --- |
|
||||
| `off` | 不参与均衡 |
|
||||
| `dry-run` | 只报告「将释放哪条」,不动任何东西(默认) |
|
||||
| `on` | 真正释放 |
|
||||
|
||||
只读接口 `GET /cluster/balance` 返回本节点视角:`selfForwards` / `share` /
|
||||
`totalForwards` / `aliveNodes` / `selfOverShare`、`wouldRelease`、`releasing`、
|
||||
`blockedBy`(为何暂不动的机器原因)、`mode` / `modeSource` / `canControl`。
|
||||
该接口**不改变任何状态** —— 反复轮询不会启动、延迟或取消一次释放。
|
||||
|
||||
## 测试
|
||||
|
||||
@ -263,6 +323,9 @@ webui4frpc(单二进制,无 frp 依赖,前端 go:embed)
|
||||
# 后端
|
||||
go test ./...
|
||||
|
||||
# 单包(负载均衡规则与状态机)
|
||||
go test ./internal/cluster/ -run TestShare -v
|
||||
|
||||
# 前端类型检查
|
||||
cd web && npm run type-check
|
||||
cd web && npm run build
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user