Go Worker Pool 关闭:让任务停止有边界、结果有去处

背景 关闭任务队列之前如果仍有提交者写入,会发生 send on closed channel。关闭一次和关闭安全不是同一件事。 核心判断 先通过统一入口停止提交,再等待所有提交者退出。 唯一协调者关闭 jobs,worker 遍历队列排空后退出。 最后等待 worker;任务本身仍应遵守超时与取消。 最小示例 下面保留核心逻辑;业务类型、调用入口和环境配置按项目补齐。 // 前提:统一入口已拒绝新提交,所有可能发送 jobs 的协程都已退出。 // 仅由协调者调用,不从 worker 内调用。 func (p *Pool) drain() { p.once.Do(func() { close(p.jobs) p.wg.Wait() }) } func (p *Pool) worker(ctx context.Context) { defer p.wg.Done() for job := range p.jobs { job.Run(ctx) } } 边界与误区 sync.Once 只能防止重复 close,不能防止并发 send。示例的 drain 要在提交者已经退出后由协调者调用,不得从 worker 自身调用以免等待自己。 验证方式 用竞态检测测试提交与停止交错,再验证空队列、阻塞任务和重复停止。明确关闭是排空任务还是丢弃任务,并对未完成结果提供可追踪状态。 小结 关闭时先禁止新提交,再关闭队列并等待 worker,任务自身要响应 context。

2026年9月21日 · 1 分钟 · BvBeJ

Kubernetes CronJob 稳定性:错过任务与重复执行治理

背景 这类问题在真实项目里很常见:高并发、复杂依赖、发布频繁、团队协作面广。只有把边界条件提前定义清楚,系统才会在压力下保持稳定。 实践要点 先定义目标:可用性、延迟、成本哪个优先。 把关键路径显式化:超时、重试、降级、回滚。 把策略写进代码和流程,而不是只停留在文档。 代码片段 apiVersion: v1 kind: ConfigMap metadata: name: sample 总结 工程实践最怕“看起来正确”。把策略做成可观测、可验证、可回滚的闭环,才能在生产环境里真正稳定运行。 稳定性不是某个技巧,而是持续的系统化约束。

2026年5月25日 · 1 分钟 · BvBeJ