聊聊并发库 Conc,你学会了吗?

上个月 sourcegraph 放出了 conc[1] 并发库,目标是 better structured concurrency for go, 简单的评价一下,每个公司都有类似的轮子,与以往的库比起来,多了泛型,代码写起来更优雅,不需要 interface, 不需要运行时 assert, 性能肯定更好,我们在写通用库和框架的时候,都有一个原则,并发控制与业务逻辑分离,背离这个原则肯定做不出通用库,标准库自带 sync.WaitGroup 用于等待 goroutine 运行结束,缺点是我们要处理控制部分,图片,代码里大量的 wg.Add 与 wg.Done 函数,所以一般封装成右侧的库,但是如何处理 panic 呢?简单的可以在闭包 doSomething 运行时增加一个 safeGo 函数,用于捕捉 recover,图片,原生 Go 要生成大量无用代码,我司 repo 运动式的清理过一波,也遇到过 goroutine 忘写 recover 导致的事故。conc 同时提供 catcher 封装 recover 逻辑,conc.WaitGroup 可以选择 Wait 重新抛出 panic, 也可以 WaitAndRecover 返回捕获到的 panic 堆栈信息,高级语言很多的基操,在 go 里面很奢侈,只能写很多繁琐代码。conc封装了泛型版本的 iterator 和 mapper,上面是使用例子,用户只需要写业务函数 handle. 相比 go1.19 前的版本,泛型的引入,使得基础库的编写更游刃有余,MaxGoroutines 默认 GOMAXPROCS 并发处理传参 slice, 也可以自定义,个人认为不合理,默认为 1 最妥,ForEachIdx 在创建 Iterator[T]{} 可以自定义并发度,最终调用 iter.ForEachIdx,ForEachIdx 泛型函数写得非常好,略去部分代码。朴素的实现在 for 循环里创建闭包,传入 idx 参数,然后 wg.Go 去运行。但是这样会产生大量闭包,我司遇到过大量闭包,造成 heap 内存增长很快频繁触发 GC 的性能问题,所以在外层只创建一个闭包,通过 atomic 控制 idx,Map 与 MapErr 也只是对 ForEachIdx 的封装,区别是处理 error,Pool 用于并发处理,同时 Wait 等待任务结束。相比我司现有 concurrency 库,先看一下支持的接口,理论上这一个足够用了,传参 Context, 返回泛型类型与错误。,这是对应的 Wait 回收函数,返回泛型结果 []T 与错误。具体 Pool 实现由多种组合而来:Pool, ErrorPool, ContextPool, ResultContextPool, ResultPool,复用方式很巧妙,如果处理速度足够快,没必要过多创建 goroutine,Stream 用于并发处理 goroutine, 但是返回结果保持顺序,实现很简单,queue 是一个 channel, 类型 callbackCh 同样也是 channel, 在真正派生 goroutine 前按序顺生成 callbackCh 传递结果,Stream 命名很差,容易让人混淆,感觉叫 OrderedResultsPool 更理想,整体非常鸡肋,超时永远是最难处理的问题,目前 conc 库 Wait 函数并没有提供 timeout 传参,这就要求闭包内部必须考滤超时,如果添加 timeout 传参,又涉及 conc 内部库并发问题题,比如这个返回值,内部 append 到 slice 时是有锁的,如果 Wait 提前结束了会发生什么?,[]T 拿到的部分结果只能丢弃,返回给上层 timeout error,通用库很容易做的臃肿,我司并发库会给闭包产生新的 context, 并继承所需框架层的 metadata, 两种实现无可厚非,这些细节总得要处理,代码量不大,感兴趣的可以看看。没有造轮子的必要,够用就行,这种库写了也没价值,[1]conc: https://github.com/sourcegraph/conc,

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/19113.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34