为什么要使用 goroutine 协程池
- 在并发编程时,可以限制 goroutine 的数量,复用资源,提升性能;
- 保持 CPU 缓存命中率,让 CPU 缓存处于活跃状态;
如何实现一个简易 goroutine 协程池
- 先对我们的目标进行抽象,池化的对象无非是启动、停止、提交任务:
- 生产端: 从 worker 池中获取一个 worker (
wp.getCh()
),并添加任务到任务队列中:
- 消费端: 从任务队列中获取任务并执行:
- 有了生产和消费端,我们来看下如何真正创建 worker 以及 worker 的任务队列:
- 接下来我们来看下如何对 worker 池进行初始化,也就是我们一开始的
Start()
方法:
我们重点来看下 workerChanCap
方法, runtime.GOMAXPROCS(0)
什么意思呢,我们来看下注释:
- 当我们传入一个参数
n
时,会设置 GOMAXPROCS
为 n
,并且返回之前的值;
- 而当
n
<1 时又什么都不做,不会修改当前设置值;
所以其实是一个获取 GOMAXPROCS
的小技巧:
-
有了启动的方法,也需要实现清理退出相关的方法,还记得我们在上面 Start()
函数预留了一个异步清理的逻辑,以及在退出时的 Stop()
逻辑:
- 在启动时,同时启动异步清理线程;
- 结束时通知并重置所有 worker 进程;
- 每个 worker 在运行时检查退出状态(mustStop)决定是否需要继续执行任务,或退出;
异步清理任务队列的 clean()
代码逻辑:
把整个代码串起来,就是在 fasthttp 库中的 workerpool 协程池的逻辑,用来高效处理 http connection 连接;
在 rolego 库中,它进行简单的调整以适配各种 fn
函数的任务处理.
Refs: