[B-08][medium] broker 上行队列按编号创建后永不回收;停机时关闭通道可能 panic(为 L-03 提供 Broker.Shutdown) #15

Closed
opened 2026-09-30 13:56:52 +08:00 by nixevol · 1 comment
Owner

编号:B-08 严重级:medium 工作线:broker(internal/broker) 来源:审查 P-15
依赖:无 被依赖:L-03 (#22)

结论与统一方案

  1. 上行队列回收(审查 P-15):队列带 pending 计数。入队时在 queuesMu 内取出或新建队列并 pending++,之后再发送;worker 处理完一项 pending--;worker 空闲超过 60 秒时加锁检查,pending==0 就把自己从 map 删除并退出。发送方拿到队列时已加过计数,worker 不会在它发送之前退出;退出后再来的消息会新建队列。
  2. Broker.Shutdown(ctx)(审查 P-06 的 broker 部分,P-06 原文附在 L-03):
    • 置 closed:OnConnect 直接拒绝新连接,PublishDown 返回已关闭;
    • 遍历 server.Clients.GetAll()(跳过内联客户端),用 ErrServerShuttingDown(0x8B)断开;
    • 在 goroutine 里调 server.Close(),受 ctx 限时;
    • 最后停止上行 worker 与 B-03 的每连接发送 goroutine。
    • 不再关闭数据通道,改用 done 通道加 WaitGroup,发送方在 select 里同时看 done,从根上消除向已关闭通道发送的 panic。

改动文件

internal/broker/broker.go、queue.go。

与其他问题的交互 / 冲突说明

  • L-03 依赖本条的 Shutdown。
  • 若 B-03 已合入,Shutdown 一并收尾每连接发送 goroutine;若未合入,B-03 实现时在 Shutdown 中补上。

验收与测试

  • 100 个端连上各发一帧后断开,空闲期过后 len(queues)==0,goroutine 数回落。
  • 入队与回收并发的压力测试。
  • Shutdown 期间并发发上行不 panic;已登录客户端收到 0x8B。

问题明细(各区审查原文,证据含文件与行号)

以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。解决方案以本 issue 上方的"结论与统一方案"为准;原文里的方案与之不一致时,按上方执行。

[P-15] uplinkQueue 按端编号创建后永不回收

  • 严重级:medium
  • 分类:并发 / 资源
  • 现象与影响:
    • 每个曾经发过上行的端都会常驻一个 goroutine 和约 28 KiB 的通道缓冲(256 项,每项是 ConnInfo 的 88 字节加切片头 24 字节)。除了 Close,没有任何地方删除。
    • 按 1 万端设计,进程运行期间连过的端越多,占用越大:约 300 MB 以上、1 万个 goroutine。已删除的端也不释放。
  • 证据:broker.go:482-491;queue.go:16-45。
  • 文档依据:PRD 第 8 节规模要求。
  • 为何不是故意设计:没有记录。
  • 解决方案:
    • 队列带一个 pending 计数。入队时在 queuesMu 锁内取出或新建队列并 pending++,之后再发送;worker 处理完一项就 pending--。
    • worker 空闲超过 60 秒时加锁检查,pending==0 就把自己从 map 里删掉并退出。发送方拿到队列时已经加过计数,worker 不会在它发送之前退出;退出后再来的消息会新建队列。
    • 停机改用 done 通道(配合 P-6)。
  • 改动文件:internal/broker/broker.go、queue.go
  • 与其他模块的交互/冲突风险:同一端的串行语义不变。
  • 需补测试:100 个端连上发一帧后断开,空闲期过后 len(b.queues)==0,goroutine 数回落;入队和回收并发的压力测试。
  • 置信度:代码阅读确定

复审基线:main 4059a15(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。

**编号**:B-08 **严重级**:medium **工作线**:broker(internal/broker) **来源**:审查 P-15 **依赖**:无 **被依赖**:L-03 (#22) ### 结论与统一方案 1. **上行队列回收**(审查 P-15):队列带 pending 计数。入队时在 `queuesMu` 内取出或新建队列并 `pending++`,之后再发送;worker 处理完一项 `pending--`;worker 空闲超过 60 秒时加锁检查,`pending==0` 就把自己从 map 删除并退出。发送方拿到队列时已加过计数,worker 不会在它发送之前退出;退出后再来的消息会新建队列。 2. **`Broker.Shutdown(ctx)`**(审查 P-06 的 broker 部分,P-06 原文附在 L-03): - 置 closed:`OnConnect` 直接拒绝新连接,`PublishDown` 返回已关闭; - 遍历 `server.Clients.GetAll()`(跳过内联客户端),用 `ErrServerShuttingDown`(0x8B)断开; - 在 goroutine 里调 `server.Close()`,受 ctx 限时; - 最后停止上行 worker 与 B-03 的每连接发送 goroutine。 - 不再关闭数据通道,改用 done 通道加 WaitGroup,发送方在 select 里同时看 done,从根上消除向已关闭通道发送的 panic。 ### 改动文件 `internal/broker/broker.go`、`queue.go`。 ### 与其他问题的交互 / 冲突说明 - L-03 依赖本条的 `Shutdown`。 - 若 B-03 已合入,Shutdown 一并收尾每连接发送 goroutine;若未合入,B-03 实现时在 Shutdown 中补上。 ### 验收与测试 - 100 个端连上各发一帧后断开,空闲期过后 `len(queues)==0`,goroutine 数回落。 - 入队与回收并发的压力测试。 - Shutdown 期间并发发上行不 panic;已登录客户端收到 0x8B。 --- ### 问题明细(各区审查原文,证据含文件与行号) > 以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。**解决方案以本 issue 上方的"结论与统一方案"为准**;原文里的方案与之不一致时,按上方执行。 #### [P-15] uplinkQueue 按端编号创建后永不回收 - **严重级**:medium - **分类**:并发 / 资源 - **现象与影响**: - 每个曾经发过上行的端都会常驻一个 goroutine 和约 28 KiB 的通道缓冲(256 项,每项是 ConnInfo 的 88 字节加切片头 24 字节)。除了 Close,没有任何地方删除。 - 按 1 万端设计,进程运行期间连过的端越多,占用越大:约 300 MB 以上、1 万个 goroutine。已删除的端也不释放。 - **证据**:`broker.go:482-491`;`queue.go:16-45`。 - **文档依据**:PRD 第 8 节规模要求。 - **为何不是故意设计**:没有记录。 - **解决方案**: - 队列带一个 `pending` 计数。入队时在 `queuesMu` 锁内取出或新建队列并 `pending++`,之后再发送;worker 处理完一项就 `pending--`。 - worker 空闲超过 60 秒时加锁检查,`pending==0` 就把自己从 map 里删掉并退出。发送方拿到队列时已经加过计数,worker 不会在它发送之前退出;退出后再来的消息会新建队列。 - 停机改用 done 通道(配合 P-6)。 - **改动文件**:`internal/broker/broker.go`、`queue.go` - **与其他模块的交互/冲突风险**:同一端的串行语义不变。 - **需补测试**:100 个端连上发一帧后断开,空闲期过后 `len(b.queues)==0`,goroutine 数回落;入队和回收并发的压力测试。 - **置信度**:代码阅读确定 --- <sub>复审基线:main `4059a15`(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。</sub>
nixevol added the P2-mediumlane/brokerreview-2026-09-30 labels 2026-09-30 13:56:52 +08:00
Author
Owner

已合入 origin/main 0c9b459。落地提交 91e887b fix: 完成 broker 复审 B-03 至 B-12 (#15)。L-03 停机顺序见 b40ef5c。

已合入 origin/main `0c9b459`。落地提交 `91e887b` fix: 完成 broker 复审 B-03 至 B-12 (#15)。L-03 停机顺序见 `b40ef5c`。
Sign in to join this conversation.