|
|
46e8bc3703
|
fix(cluster): 停用的转发会在重启后自己复活 + 令牌轮转日志刷屏
从线上三节点(192.168.2.{30,106,60})的日志里挖出四个问题,本轮修三个。
## 1. 停用的转发会复活(功能性缺陷,实测仍在发生)
线上现象:`minecraft` 在 store 里 disabled=1,worker 却仍在跑,今天
09:46 还在刷 `connect to local service [192.168.2.60:25565]: connection
refused` —— 对着一个用户刻意没启的本地服务死刷。同时三台 logs 里躺着
13956 / 3769 条 `proxy [x] already exists`,每 33 秒一轮。
四处叠加导致:
- stopForward 先读 link,再 SetLinkDisabled(true),然后把**改之前**的
副本交给 RevokeTask ⇒ published task 带 disabled=false(实测 id/flag
都对不上:topology 里 link.id=223,store 里同一行是 199)
- ClaimFn **无条件** SetLinkDisabled(...,false)。原意是"重新认领时清掉
停用标记",但启动 reconcile 只要 worker 不在就重新 Claim ⇒ 每次重启
都是"先清标记再起 worker"
- RevokeFn 停了 worker 却**没删 topology 条目**,条目活过 worker
- 于是下次重启 reconcile 看到"owned 但 worker 不在"→ 再次 Claim → 死循环
修法(把 disabled 的所有权交回两个用户动作):
- Claim **只读** disabled 决定要不要起 worker;为 true 时连 topology
条目一起摘掉,绝不复活
- 启动 reconcile 先按 store 跳过 disabled 的条目(省掉无谓的
claim→skip 往返)
- RevokeFn 除停 worker 外,同时 RemoveTopologyEntry —— 撤销必须是
完整退役,不能只是"停一下"
- stopForward 把 Disabled=true 随 task 发布出去,让持有该转发的节点
即使本地 store 行陈旧也能判断这次停用是用户主动的
## 2. 令牌轮转日志零信息量却占满磁盘
每轮固定 3 行(OnToken cycle=N / forward cycle=N / token-send -> 200),
2 轮/秒,实测本机 **355 行/分钟、7 天 357 万行**,把真事件全淹了。
同一份信息(cycle / lastSync / roundDelayMs / 成员存活)本来就能从
GET /api/manager/cluster/ring 结构化拿到。
加 W4F_DEBUG 开关(沿用项目既有 W4F_ 前缀约定):稳态三行降级为 debug、
默认关闭;**失败路径一律保留** —— 发送失败、陈旧令牌、非 2xx 正是别人
grep 的对象,静音它们是坏交易。实测同样 12 秒:36 行 → 4 行。
## 3. Link.ID 在 ReplaceLinks 之后必然失效
ReplaceLinks 是 DELETE + 重新 INSERT,sqlite 给每行**新的自增 id**。
任何在改写前捕获的 Link(典型:随 token 环跑的 Link)手里的 id 要么查无
此行,要么命中另一条转发 —— 实测捕获 alpha id=1,改写后新表是 3/4/5,
GetLink(1) 直接落空。
新增 LinkByTriple(local, remote, port) 按自然键查(业务代码本来就一律用
这个三元组标识转发),并把 claim/reconcile 切过去。查无行返回
(Link{}, false, nil) 而非 error:新建的转发没有行,应当照常启动。
## 4. homeagent_device 孤儿(已澄清,非独立缺陷)
它 disabled=1 且从不在 topology 里,是缺陷 1 的另一面(停用标记没进
token),随本次修复覆盖,无需单独处理。
## 测试
新增 4 个测试文件,重点是**验证测试本身抓得住 bug**:
- 临时回退 `ln.Disabled = true` 这行 → TestStopForwardPublishesDisabled-
FlagInRevokeTask 如期变红,还原后变绿
- ⚠️ 第一版回归测试只断言 store 层,是**假绿**:newTestHandler 的 Ring
为 nil,RevokeTask 那条(真正坏掉的)路根本没执行。补了带 ring 的
newRingTestHandler,直接断言**发布出去的 task 上的 flag**
- LinkByTriple 在 ReplaceLinks 前后保持稳定;GetLink(id) 的失效被固化成
一个可见的说明性测试
- 停用/start 往返、per-forward 停用不误伤兄弟转发
- 错误路径不静音、W4F_DEBUG 各种取值
go build / go vet / go test ./... 全绿,gofmt 干净。
|
2026-09-26 10:02:55 +08:00 |
|
|
|
94b6396738
|
docs: 更新 README 与 cluster-api — per-forward 模型/网络负载/审计CSV/三级角色/session登录
README:
- 特性: per-forward 独立进程、NIC 负载采样、冲突检查、Del 键删除
- 认证: session-cookie 登录 + 三级角色 (superadmin/admin/viewer)
- 审计: 4 个 CSV 导出端点说明
- 构建: dist 不再进 git (编译前需 cp -r)
- 数据目录: 配置/日志路径改为 per-forward 键式
- 架构: 更新模块说明 (worker_key/session/audit)
- API 表: 新增 login/logout + 审计导出 4 端点
- gofmt: store.go 注释对齐
docs/cluster-api.md:
- §9 审计 CSV 导出: 四个端点用法、示例行、公式注入防御说明
|
2026-08-24 23:52:16 +08:00 |
|
|
|
f90627f542
|
Merge remote-tracking branch 'origin/main'
# Conflicts:
# internal/httpapi/dist/assets/index-CL42Ur3_.css
# internal/httpapi/dist/assets/index-CbqC9m-j.js
# internal/httpapi/dist/assets/index-RFHYrCiX.css
# internal/httpapi/dist/assets/index-jvouiCgh.css
# internal/httpapi/dist/index.html
# internal/store/store.go
# web/src/api.ts
# web/src/views/ClusterView.vue
|
2026-08-24 23:30:19 +08:00 |
|
|
|
4a41608d94
|
refactor: 审查修复 — netload 消除重复 /sys 读 + 全项目 gofmt
- netload_linux.go: SampleNetLoad 聚合循环不再对每接口重复
readIfaceSpeed (snapshot 已汇总 cur.capMbps), 每次采样省 N 次 /sys 读
- gofmt -w: ring.go/ring_engine.go/auth.go/handlers.go/handlers_logs.go/
handlers_users.go/store.go 结构体字段对齐与注释缩进
- README.md: markdownlint 自动修复 (MD028/MD040)
审查结论: 令牌环本身即互斥协议 — OnToken(收令牌)与 StartRing(发令牌)
在同一节点上由令牌串行化, 不存在需要加锁的竞争; WatchLeader 的读为
良性读, 无需 mutex
|
2026-08-24 22:24:35 +08:00 |
|
|
|
f29ec81e4a
|
feat: session-cookie login/logout + three-tier roles (superadmin/admin/viewer) with read-only UI + remove pink theme
- cookie-based auth (/login /logout) replacing Basic Auth for UI, enabling logout
- roles: superadmin (account management only), admin (full except accounts), viewer/audit (read-only status+cluster, export logs)
- readonly accounts hide edit buttons (added remote node, group ops, canvas layout/save/import, cluster manage, install) instead of greying them
- auditors see status+cluster only; ordinary admins lose the accounts nav; last-admin guard covers superadmin
- remove pink theme entirely (switcher, [data-theme=pink], leftover localStorage), keep white/blue
|
2026-08-20 09:08:15 +08:00 |
|
|
|
eda9bb9597
|
feat: cluster reliability (leader failover, crash rejoin, key exchange) + auth/users + canvas/forwards enhancements + comprehensive README + API docs
- Cluster: forwardToNext offline detection (leader+non-leader), WatchLeader 1s heartbeat fallback, 409 for standalone nodes, Node.NodeKey key exchange via token ring, ClusterPeers persistence + auto-rejoin, Forward delegates to forwardToNext (bugfix)
- Auth: Basic Auth (flag-creds fast path) + bcrypt users (admin/viewer) + Bearer API keys (read/write/admin scope)
- Frontend: UsersView (accounts+API keys), ClusterView (ring/nodeKey/tasks/topology/log), StatusView (group management, per-proxy status), CanvasView (edge toggle/group), PortEdge (disabled/group labels)
- API: handlers split (canvas/forwards/users/logs), canvas export/import, forwards group start/stop/assign/delete, cluster endpoints
- Docs: comprehensive README rewrite (all flags/APIs/auth/cluster), docs/cluster-api.md (cluster management API reference)
- Deploy: run-cluster.sh now 4-node ring + 1 isolated standalone, test-forward.sh updated for 4 nodes
- Removed plan.md (design notes consolidated into README + API docs)
|
2026-08-19 21:09:24 +08:00 |
|
|
|
40980944e5
|
feat(M6): localOnly forward option (loopback→LAN rewrite for cluster, local direct), canvas diff-based create/revoke commands, revoke task semantics, topology derived canvas on sync nodes, LAN addr helper
|
2026-08-18 09:44:38 +08:00 |
|
|
|
467c7124ab
|
feat: M3 load balancing + health check (model/render/admin API status/UI)
|
2026-08-17 17:45:03 +08:00 |
|
|
|
bd3a62a017
|
fix: worker 进程并发 double-close panic + 状态页连接语义重构 + 集群页骨架
- process: spawn 不再重复起 supervise goroutine(Restart 触发旧 supervise close doneCh 后再 close → panic);新增 closeOnce/supervising 守卫;Start 首次起 supervise,重启循环在同一 goroutine 内
- httpapi: status 增加 connState(connected/connecting/failed/not_started/disabled),由 worker 日志探测真实 frps 连接(不再把本地 worker 状态误当远程 frps 状态)
- StatusView: 远程卡片主状态改为连接状态徽标;启停按钮标注为控制本地 frpc worker;本地转发区保留 worker 状态显示
- 新增 ClusterView 集群页骨架(M3 LB+健康检查载体)+ App.vue 导航接入
- render: bandwidthLimit 从 proxy 顶层移入 transport 段(frpc 0.61 正确 schema,修复真实连不上的 bug)
|
2026-08-17 15:13:25 +08:00 |
|
|
|
58906c5a81
|
feat: M2 HTTP/HTTPS 完善
- store: Local 增加 customDomains/subdomain/locations/hostHeaderRewrite/httpHeaders/basicAuth;Remote 增加 vhostHttpPort;migrate() 补列;CRUD 读写(JSOm 编解码)
- render: http/https proxy 输出 customDomains/subdomain/locations/hostHeaderRewrite/httpHeaders/basicAuth
- main: renderRemote 透传 M2 字段(customDomains 逗号拆分 splitCSV)
- web: LocalNode 折叠 HTTP 路由高级区;RemoteNode vhostHTTPPort;StatusView 显示 HTTP 访问端口
- 测试: TestRenderHTTPAdvanced / TestRenderHTTPSUsesCustomDomains;端到端 PUT canvas→config 验证通过
|
2026-08-17 12:59:12 +08:00 |
|
|
|
07f25ea067
|
feat: M1 高级传输参数(P0)
- store: Local 增加 useEncryption/useCompression/bandwidthLimit/poolCount/metadatas/annotations;Remote 增加 transportProtocol/transportTls/transportPool/transportTlsServerName;新增 migrate() ALTER TABLE 迁移旧库
- render: 输出 transport 段(protocol/tls/poolCount)与 proxy 高级字段;补 TestRenderTransportAdvanced/OmittedWhenEmpty
- main: renderRemote 闭包透传 M1 字段到 render.Proxy
- web: LocalNode/RemoteNode 折叠高级区表单,types.ts 接口扩展
- 验证:go test 全绿、vue-tsc/build 通过、端到端 PUT canvas→frpc JSON 输出完整
|
2026-08-17 12:28:54 +08:00 |
|
|
|
5237e3b594
|
fix: 注册 PUT /api/manager/settings 使设置保存生效
server.go NewServeMux 按方法分发到 handleSettingsPut(原仅注册 GET,PUT 静默返回旧值)
新增 TestSettingsPutRoundTrip 回归测试;gofmt 清理历史格式问题
|
2026-08-17 12:00:34 +08:00 |
|
|
|
c1936887a2
|
webui4frpc: 独立可用的可视化 frpc 控制器 (M0)
- 零 frp 源码依赖,单二进制 (Go + Vue3 + VueFlow + Element Plus)
- 画布多对多连线,渲染 tcp/udp/http/https frpc 配置
- worker 进程管理:自愈、日志轮转、崩溃退避重启
- frpc 一键安装 (GitHub Releases) + 手动指定路径
- 三页 UI:状态(默认)/连接配置/设置
- 状态页实时节点/转发状态,节点可增删改启停
- 画布冲突检查:端口/域名冲突标红 + 弹窗拦截保存
- backend 单测覆盖 store/render/process/httpapi/install
- plan.md + FRPC_FEATURES_AUDIT.md 文档
|
2026-08-17 11:00:26 +08:00 |
|