酷Go推荐 协程池 ants 介绍

wentao · 2021年09月17日 · 最后由 wentao 回复于 2021年09月30日 · 285 次阅读

推荐理由

协程泄漏引发的血案,想必各位 gopher 都经历过,通过协程池限制 goroutine 数是一个有效避免泄漏的手段。今天介绍的 ants 库是公认且优秀的协程池实现。ants Github 主页上的简介:

ants 是一个高性能的 goroutine 池,实现了对大规模 goroutine 的调度管理,允许使用者在开发并发程序的时候限制 goroutine 数量,复用资源,达到更高效执行任务的效果。

功能介绍

  • 自动调度海量的 goroutines,复用 goroutines
  • 定期清理过期的 goroutines,进一步节省资源
  • 提供了大量有用的接口:任务提交、获取运行中的 goroutine 数量、动态调整 Pool 大小、释放 Pool、重启 Pool
  • 优雅处理 panic,防止程序崩溃
  • 资源复用,极大节省内存使用量;在大规模批量并发任务场景下比原生 goroutine 并发具有更高的性能
  • 非阻塞机制

使用指南

目前测试通过的 Golang 版本:

v1.8.x** ~ v1.16.x** 的所有版本。

安装

go get -u github.com/panjf2000/ants

使用 v2 版本 (开启 GO111MODULE=on):

go get -u github.com/panjf2000/ants/v2

代码示例

ants 支持两种协程池,Pool 和 PoolWithFunc,差别在于,Pool 每个任务是一个函数,PoolWithFunc 任务函数在初始化时确定,每个任务只是不同的入参调用该函数。

Pool

import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"

    "github.com/panjf2000/ants/v2"
)

func demoFunc() {
    time.Sleep(10 * time.Millisecond)
    fmt.Println("Hello World!")
}

func main() {
    // 释放ants的默认协程池
    defer ants.Release()

    var wg sync.WaitGroup
    // 任务函数
    syncCalculateSum := func() {
        demoFunc()
        wg.Done()
    }
    for i := 0; i < 100; i++ {
        wg.Add(1)
        // 提交任务到默认协程池
        _ = ants.Submit(syncCalculateSum)
    }
    wg.Wait()
    fmt.Printf("running goroutines: %d\n", ants.Running())
    fmt.Printf("finish all tasks.\n")
}

PoolWithFunc

import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"

    "github.com/panjf2000/ants/v2"
)

var sum int32

func myFunc(i interface{}) {
    n := i.(int32)
    atomic.AddInt32(&sum, n)
    fmt.Printf("run with %d\n", n)
}

func main() {
    // 初始化协程池
    p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
        myFunc(i)
        wg.Done()
    })
    // 释放协程池
    defer p.Release()
    // 提交任务
    for i := 0; i < runTimes; i++ {
        wg.Add(1)
        _ = p.Invoke(int32(i))
    }
    wg.Wait()
    fmt.Printf("running goroutines: %d\n", p.Running())
    fmt.Printf("finish all tasks, result is %d\n", sum)
}

协程池配置

ants 协程池支持以下配置项:

  • 协程池大小设置,可通过
  • worker 协程过期时间,过期后的协程会被清理
  • 内存预分配,是否初始化 Pool 的时候分配 worker 资源
  • 最大阻塞任务数,默认 0,任务阻塞直到分配到 worker;当非 0 时,达到最大任务数,不执行任务并返回 overload
  • 非阻塞提交,默认否,任务无 worker 执行时阻塞,当为 true 时,无 worker 则立即返回 overload
  • 自定义 panic 处理函数
  • 自定义日志函数

代码片段:

// 设置配置项
options := Options{}
options.ExpiryDuration = time.Duration(10) * time.Second
options.Nonblocking = true
options.PreAlloc = true
// 初始化
poolOpts, _ := NewPool(10, WithOptions(options))

以上是 ants 的基本使用,更详细的内容可以参考 ants 源码。

总结

协程池通过复用和限制 goroutine 数,可以减轻 runtime 调度压力,避免过多的 gorouutine 占用系统 cpu 和内存资源,ants 作为协程池实现优秀代表,功能丰富且简单易用,推荐在适合的场景使用。

参考资料

  1. https://github.com/panjf2000/ants
  2. https://strikefreedom.top/high-performance-implementation-of-goroutine-pool
更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
Orichalcum GoCN 每日新闻 (2021-09-17) 中提及了此贴 09月18日 07:48

很早就用了 开销低也需要节制

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册