mirror of
https://gitcode.com/JianFeeeee/webui4frpc.git
synced 2026-10-03 23:53:59 +00:00
feat: per-forward worker 模型 — 每条转发独立 frpc 配置+独立进程
核心改动(ring 协议不变,Task 本来就是 {Local,Remote,Link} 三元组):
- process.WorkerKey: worker 键改为 'local~remote~port' 三元组
- renderForward: 每条 forward 渲染只含 1 个 proxy 的独立 frpc 配置
(替代 renderRemote 把该 remote 全部 forwards 塞进一个进程)
- ClaimFn/RevokeFn: 认领/撤销只操作这一条 forward 自己的进程
- SyncWorkers/auto-start: 只拉起 localOnly 转发的独立进程,
集群转发由 ring 认领节点拉起 (消除三台争抢 proxy already exists)
- RemoteStatus/StartRemote/StopRemote/RestartRemote: remote 级聚合辅助,
保持 /profiles API 形状不变, 前端零改动
- handleStatus/logs: 按 worker key 解析真实 remote 名
效果: 三台节点的 frpc 各自只注册自己拥有的 proxy, 单条转发故障不再波及兄弟
This commit is contained in:
@ -287,6 +287,88 @@ func (m *Manager) ListWorkers() []string {
|
||||
return out
|
||||
}
|
||||
|
||||
// RemoteWorkers returns the worker keys of all per-forward workers whose key
|
||||
// parses to the given remote name. In the per-forward model every link has
|
||||
// its own process keyed "local~remote~port"; this aggregates them so remote-
|
||||
// centric callers (status page, profile endpoints) can report an overall
|
||||
// view without knowing the key format.
|
||||
func (m *Manager) RemoteWorkers(remote string) []string {
|
||||
var out []string
|
||||
for _, key := range m.ListWorkers() {
|
||||
if _, r, _, ok := ParseWorkerKey(key); ok && r == remote {
|
||||
out = append(out, key)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// RemoteStatus summarizes a remote's per-forward workers into one Status:
|
||||
// running when ANY forward worker runs; crashed/starting/restarting take
|
||||
// priority in that order; stopped (has=false) when no worker exists.
|
||||
// This keeps the legacy per-remote status shape working on top of the
|
||||
// per-forward worker model.
|
||||
func (m *Manager) RemoteStatus(remote string) (Status, bool) {
|
||||
keys := m.RemoteWorkers(remote)
|
||||
if len(keys) == 0 {
|
||||
return Status{State: "stopped"}, false
|
||||
}
|
||||
summary := Status{State: "stopped"}
|
||||
worst := -1 // rank: running=0 < others=1 < crashed=2
|
||||
for _, k := range keys {
|
||||
st, _ := m.Status(k)
|
||||
rank := 1
|
||||
switch st.State {
|
||||
case "running":
|
||||
rank = 0
|
||||
case "crashed":
|
||||
rank = 2
|
||||
}
|
||||
if rank > worst || (rank == worst && summary.State == "stopped") {
|
||||
if rank != worst || st.State != "stopped" {
|
||||
summary = st
|
||||
worst = rank
|
||||
}
|
||||
}
|
||||
}
|
||||
return summary, true
|
||||
}
|
||||
|
||||
// StartRemote starts every per-forward worker of one remote. Missing workers
|
||||
// are skipped; the first error wins.
|
||||
func (m *Manager) StartRemote(remote string) error {
|
||||
var firstErr error
|
||||
for _, key := range m.RemoteWorkers(remote) {
|
||||
if err := m.Start(key); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
return firstErr
|
||||
}
|
||||
|
||||
// RestartRemote restarts every per-forward worker belonging to one remote
|
||||
// (used where the old model had a single per-remote worker). Missing workers
|
||||
// are skipped; the first error wins.
|
||||
func (m *Manager) RestartRemote(remote string) error {
|
||||
var firstErr error
|
||||
for _, key := range m.RemoteWorkers(remote) {
|
||||
if err := m.Restart(key); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
return firstErr
|
||||
}
|
||||
|
||||
// StopRemote stops every per-forward worker of one remote.
|
||||
func (m *Manager) StopRemote(remote string) error {
|
||||
var firstErr error
|
||||
for _, key := range m.RemoteWorkers(remote) {
|
||||
if err := m.Stop(key); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
return firstErr
|
||||
}
|
||||
|
||||
// StopAll stops all workers (used on manager shutdown).
|
||||
func (m *Manager) StopAll() {
|
||||
m.mu.Lock()
|
||||
|
||||
Reference in New Issue
Block a user