Skip to content

fix(cluster): 跨节点同名流 KV 冲突重入死锁 + G.711 音频 channels + gotask v1.0.5 根治#6

Merged
eanfs merged 4 commits into
developfrom
test/cluster-3node-e2e
Jun 3, 2026
Merged

fix(cluster): 跨节点同名流 KV 冲突重入死锁 + G.711 音频 channels + gotask v1.0.5 根治#6
eanfs merged 4 commits into
developfrom
test/cluster-3node-e2e

Conversation

@eanfs

@eanfs eanfs commented Jun 3, 2026

Copy link
Copy Markdown
Owner

概述

修复 cluster 跨节点同名流 KV 冲突导致的 Server.Streams 事件循环重入死锁,连带修复 G.711 音频录制元数据,并切到根治版 gotask。

提交

  • fix(cluster): 跨节点同名流 KV 冲突重入死锁: RC1 冲突停流重入 SafeGet 死锁→pub.Stop 闭包直调;RC2 阻塞 acquire 在 Streams 循环→dispatch 异步;RC3 relay 误抢锁→权威 activeRelays;次生 release-guard 不删属主 peer 键
  • fix(rtsp): G.711(PCMA/PCMU)channels=0→ NewPCMACtx()/NewPCMUCtx() 默认(mono/8000/16)
  • chore(deps): 切 gotask→github.com/eanfs/gotask v1.0.5(库层根治 Job.Call 同 goroutine 重入死锁)

验证

  • 单测全绿(offload/release-guard/isActiveRelay 守卫)
  • 3 节点活集群真机:同名拉流干净停止不死锁、保留属主、auto-relay 15s/147帧、跨节点 play+record(2K)+S3+完整性
  • BuildInfo 确认链接 eanfs/gotask v1.0.5

关联:gotask 库层修复 PR(eanfs/gotask 已发 v1.0.5)

eanfs added 4 commits June 3, 2026 12:47
非属主节点对与属主同名的 streamPath 拉流/订阅时,first-write-wins 冲突处理
在 Server.Streams 事件循环上同步执行 acquire(阻塞 Consul I/O)并经
Server.Streams.SafeGet(m.Call) 重入同一循环,gotask 的 Call 不识别已在本
循环 goroutine,入队+阻塞导致永久死锁,stream-list 与新订阅/发布全挂。

- RC1: OnPublish 直接绑定 pub.Stop 闭包,不再 SafeGet 反查(消除重入)
- RC2: acquire+冲突停流经 sr.dispatch(一次性 callbackGoTask)异步挪到
  StreamRegistry 自己的事件循环,离开 Server.Streams 调用栈
- RC3: relay publisher 判据改用 cluster 插件权威自持的 activeRelays
  (isActiveRelay),而非易丢的 PullProxyConfig.Description(EnsurePullProxy
  命中已存在 pull-proxy 会丢弃新 conf 的 cluster-relay 标记)
- 次生: 加 acquired 标志,冲突未拥有键时不 release,避免删掉属主 peer 的 KV 键

新增回归守卫: ConflictHandlingOffloaded / ConflictDoesNotReleasePeerKey /
SuccessfulAcquireReleasesOnDispose / IsActiveRelay。
真机回归(3 节点活集群): incident2 同名拉流干净停止+不死锁+属主保留;
incident1 auto-relay 无 acquire 失败+15s/147帧持续供流。
RTSP 收 G.711 时用空 codec.PCMACtx{}/PCMUCtx{}(Channels/SampleSize=0),
而 G.711 的 SDP 'PCMA/8000' 不带声道数,RTPCodecParameters.Channels=0 时
直接赋值会写出 channels=0,录制的 mp4 音频轨元数据非法,ffprobe 无法解析
整文件(Failed to open codec / 0 channels)。

- 改用 codec.NewPCMACtx()/NewPCMUCtx() 作默认(G.711 mono: SampleRate=8000,
  Channels=1, SampleSize=16),仅当 SDP 给出有效值(>0)才覆盖
- 真机验证: node-3 录 camera27 → ffprobe channels=1 + 全文件解码 exit=0

附带: EnsurePullProxy 命中已存在 pull-proxy 复用、丢弃新 conf 时加非静默
Debug 日志(行为不变,正确语义不覆盖已有配置;relay 标记已由 activeRelays
权威判定)。
eanfs/gotask v1.0.5 根治了 Job.Call 同 goroutine 重入死锁(本次 cluster
Streams 事件循环死锁的底层原因)。因 fork 模块路径已改为 github.com/eanfs/gotask
且内部子包自引用同步更新,replace 方式会触发 'two different module paths' 冲突,
故全仓 import 由 langhuihui/gotask 改为 eanfs/gotask。

- 91 个 .go 文件 import 路径更新 + go.mod/go.sum
- 二进制 BuildInfo 确认链接 eanfs/gotask v1.0.5
- cluster 测试通过
@eanfs
eanfs merged commit 7b1cbfd into develop Jun 3, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant