golang协程池(goroutine池)ants库实践

 golang中goroutine由运行时管理,使用go关键字就可以方便快捷的创建一个goroutine,受限于服务器硬件内存大小,如果不对goroutine数量进行限制,会出现Out of Memory错误。但是goroutine泄漏引发的血案,想必各位gopher都经历过,通过协程池限制goroutine数一个有效避免泄漏的手段,但是自己手动实现一个协程池,总是会兼顾不到各种场景,比如释放,处理panic,动态扩容等。那么ants是公认的优秀实现协程池。

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

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

Go 语言最大的特色之一,就是其从语言的层面支持并发。Go 语言使用了其特有的 goroutine 作为最基本的并发执行单元,以协程的方式,实现了更加轻量和高效的并发执行。然而,goroutine 缺乏一个高级的管理机制,原生情况下使用,要实现动态调整数量、内存资源复用、错误处理等,往往需要编写比较多的底层代码逻辑。Ants,这个 goroutine 池实现,提供了对于大规模 goroutine 的管理功能,相比原生实现,资源使用率和执行性能都有了很大的提升。

ants pool

简介

Ants,是 panjf2000 在 Github 上开源的高性能 goroutine 池,项目位于 ,目前版本为 v2.4.0。Ants 实现了对于大规模 goroutine 的调度管理和复用,允许使用者在开发 Golang 并发程序时限制 goroutine 数量,复用资源,达到更高效执行任务的效果。Ants 提供了大量有用的接口,包括:任务提交、获取运行中的 goroutine 数量、动态调整池带下、释放和重启池等。Ants 通过优秀的资源复用策略,极大地节省内存使用量,在大规模批量并发任务场景下,比原生的 goroutine 实现的并发具有更高的性能。

Github项目

安装

Ants 使用 Go 语言开发,需要 Go 1.8.x 以上。Ants 目前同时维护 v1 和 v2 版本,安装 v1 版本:

 go get -u github.com/panjf2000/ants  

v2 版本需要使用 go module 支持,开启 GO111MODULE=on:

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

godoc文档

示例

Ants 对于任务的执行原理比较直观,通过一个工作池的形式维护 goroutine 集合。当向工作池提交任务时,从池中取出 worker 来执行。如果已经存在可用的 goroutine 了,那么直接开始执行,如果没有,则需要判断是否已经达到容量上限。如果还没有超过,那就意味着可用的 worker 比容量更少,此时启动新的 worker 来执行。而如果容量已经用完,就依据是否为阻塞模式,来马上返回,或是阻塞等待。

ants工作池等待

当任务执行完毕,对应的 worker 就会得到释放,重新回到池中,等待下一个任务的调度,实现 goroutine 的复用。

ants复用

完整的工作池 worker 调度的逻辑和流程如下:

ants任务执行流程

Ants 支持不同的使用方式,可以直接使用 Submit 接口,使用默认配置的工作池完成任务执行。Submit 函数的定义如下:

 func Submit(task func()) error  

通过提供一个函数类型的任务参数,来把任务提交到工作池执行。我们来看一个简单的使用例子:

 package mainimport ("fmt""sync""time""github.com/panjf2000/ants/v2"
)func demoFunc() {time.Sleep(10 * time.Millisecond)fmt.Println("Hello World!")
}func main() {defer ants.Release()runTimes := 1000var wg sync.WaitGroupsyncCalculateSum := func() {demoFunc()wg.Done()}for i := 0; i < runTimes; i++ {wg.Add(1)_ = ants.Submit(syncCalculateSum)}wg.Wait()fmt.Printf("running goroutines: %d\n", ants.Running())fmt.Printf("finish all tasks.\n")
}  

在这个例子中,定义了一个简单的任务函数 demoFunc,短暂休眠后打印 Hello World。在 main 函数中,使用了 sync.WaitGroup 来进行并发控制,把 demoFunc 包裹成为一个并发任务函数 syncCalculateSum。我们要把这个任务执行 1000 次,就可以通过循环,进行 1000 次的 ants.Submit 调用,把所有任务都提交到工作池执行。提交完成后,等待任务完成。程序在完成了 1000 次的 Hello World 打印后,最终完成了任务执行。

除了使用默认的工作池外,我们还可以自己实例化一个工作池,并提供容量和任务函数,使用 NewPoolWithFunc 简单完成 goroutine 池的创建:

 package mainimport ("fmt""sync""sync/atomic""time""github.com/panjf2000/ants/v2"
)var sum int32func myFunc(i interface{}) {n := i.(int32)atomic.AddInt32(∑, n)fmt.Printf("run with %d\n", n)
}func main() {runTimes := 1000// 创建一个容量为10的goroutine池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.NewPoolWithFunc,创建了一个自定义容量和任务的函数工作池,任务函数可以提供一个 interface{} 参数,方便传递数据。然后,通过函数工作池的 Invoke 接口,完成任务参数的传递和任务的提交。在这个例子中,实现了从 0 到 1000 的并发求和,最终打印出计算结果。

此外,我们还可以使用最基础的方法 NewPool 来进行 ants.Pool 结构的实例化:

 p, _ := ants.NewPool(10000)  

NewPool 的函数签名如下:

 func NewPool(size int, options ...Option) (*Pool, error)  

其接收一个容量参数,以及其他配置参数,返回指向 Pool 类型实例的指针和错误。我们可以使用 options 参数进行更为细化的配置,配置参数包括:

  • ExpiryDuration:清理 goroutine 的时间间隔。每隔一段时间,Ants 就会对池中未被使用的 goroutine 进行清理,减少内存占用;
  • PreAlloc:是否在初始化工作池时预分配内存。对于一个超大容量,且任务耗时长的工作池来说,预分配内存可以大幅降低 goroutine 池中的内存重新分配损耗;
  • MaxBlockingTasks:阻塞任务的最大数,0代表无限制;
  • Nonblocking:工作池是否是非阻塞的,这决定了 Pool.Submit 接口在提交任务时是否会被阻塞;
  • PanicHandler:任务崩溃时的处理函数;
  • Logger:日志记录器

这些参数既可以在初始化的时候通过 Option 传递,也可以使用链式调用的方法实现配置叠加,利用 WithExpiryDuration、WithPreAlloc 等方法实现。

Ants 的工作池的容量需要在初始化的时候提供,但它并不是一成不变的,可以通过 Tune 接口实现 goroutine 池容量的动态调整:

 pool.Tune(1000)
pool.Tune(100000)  

这个方法时线程安全的,不必担心动态调整带来的数据并发问题。

在使用完成后,需要对工作池进行资源释放,一般通过 defer 机制调用:

 pool.Release()  

也可以通过 Reboot 方法,把一个已经释放资源被销毁的池重新激活,投入使用:

 pool.Reboot()  

Ants 以其高性能和低消耗著称,自然有测试依据。项目作者进行了 1000 万大规模并发任务执行的性能测试,Ants 使用 70 万的 goroutine 就完成了全部任务,执行速度比原生 goroutine 提高了 100%,且内存消耗保持在不使用 Pool 的 40%。此外,还进行了吞吐量测试,使用 Ants 的吞吐性能达到了原生 goroutine 的 2 到 6 倍,而内存消耗则达到 10 到 20 倍的降低。从测试结果来看,Ants 的高性能特性名不虚传。

性能测试

总结

Ants 作为一个高性能 goroutine 池,提供了比原生 goroutine 实现更为高级的调度管理和复用机制,抽象层次更高,且充分利用池化策略,使用尽可能少的 goroutine 数量和内存占用,以更快的速度完成并发任务的执行,在大规模和高吞吐场景下,具备很强的性能优势。Ants 项目代码整洁,注释详尽,文档丰富,对于 goroutine 并发模型有较深的理解,对相关领域感兴趣的开发者可以进行参考学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Qt中使用LoadLibrary无法加载DLL

Qt系列文章目录 文章目录 Qt系列文章目录前言一、问题分析 前言 最近因项目需要使用qt做开发&#xff0c;之前使用LoadLibrary加载dll成功&#xff0c;很庆幸&#xff0c;当一切都那么顺风顺水的时候&#xff0c;测试同事却发现&#xff0c;在windows平台上个别电脑上加载dll会…

Redis BitMap/HyperLogLog/GEO/布隆过滤器案例

面试问题&#xff1a; 抖音电商直播&#xff0c;主播介绍的商品有评论&#xff0c;1个商品对应了1系列的评论&#xff0c;排序展现取前10条记录用户在手机App上的签到打卡信息&#xff1a;1天对应1系列用户的签到记录&#xff0c;新浪微博、钉钉打卡签到&#xff0c;来没来如何…

【Grafana】中文界面配置 v10.0.3

比如通过 docker run -d -p 3000:3000 -v /e/code/monitor/grafana/grafana.ini.txt:/etc/grafana/grafana.ini grafana/grafana运行一个容器&#xff08;最新是v10.0.3&#xff09;。 在 /admin/settings 可以看到 users 部分有一个 default_language 配置。 所以在挂载到 …

php代码审计,php漏洞详解

文章目录 1、输入验证和输出显示2、命令注入(Command Injection)3、eval 注入(Eval Injection)4、跨网站脚本攻击(Cross Site Scripting, XSS)5、SQL 注入攻击(SQL injection)6、跨网站请求伪造攻击(Cross Site Request Forgeries, CSRF)7、Session 会话劫持(Session Hijacking…

自动化实践-全量Json对比在技改需求提效实践

1 背景 随着自动化测试左移实践深入&#xff0c;越来越多不同类型的需求开始用自动化测试左移来实践&#xff0c;在实践的过程中也有了新的提效诉求&#xff0c;比如技改类的服务拆分项目或者BC流量拆分的项目&#xff0c;在实践过程中&#xff0c;这类需求会期望不同染色环境…

SpringCloud源码探析(九)- Sentinel概念及使用

1.概述 在微服务的依赖调用中&#xff0c;若被调用方出现故障&#xff0c;出于自我保护的目的&#xff0c;调用方会主动停止调用&#xff0c;并根据业务需要进行对应处理&#xff0c;这种方式叫做熔断&#xff0c;是微服务的一种保护方式。为了保证服务的高可用性&#xff0c;…

rknn3588如何查看npu使用情况

cat /sys/kernel/debug/rknpu/load

windows环境下编译OpenJDK12

环境&#xff1a;Windows11 目录&#xff1a; 1、下载OpenJDK12源码 下载地址&#xff1a; https://hg.openjdk.org/jdk/jdk12 点击zip下载到本地。 解压到本地。 Tip&#xff1a;注意本地路径中最好不要包含中文或空格。 2、阅读一遍doc/building.html 如果只是想构建J…

白帽黑帽与linux安全操作

目录 白帽黑帽 Linux安全 白帽黑帽 白帽&#xff08;White Hat&#xff09;和黑帽&#xff08;Black Hat&#xff09;通常用于描述计算机安全领域中的两种不同角色。白帽黑客通常被认为是合法的安全专家&#xff0c;他们通过合法途径寻找和修复安全漏洞&#xff0c;帮助企业和…

Linux/centos上如何配置管理samba服务器?

Linux/centos上如何配置管理samba服务器&#xff1f; 1 samba服务相关知识1.1 SMB协议1.2 samba工作原理1.2.1 相关进程1.2.2 samba工作流程1.2.3 samba功能 2 samba服务器安装2.1 利用光驱安装2.2 利用光盘映射文件 3 启动与停止samba服务4 配置samba服务器4.1 samba主配置文件…

解读百威亚太2023上半年财报:啤酒大年百威如何重塑高端化之路?

随着消费者的需求提升&#xff0c;啤酒行业向高端化发展&#xff0c;其中知名度较高的百威亚太、华润啤酒、青岛啤酒、燕京啤酒、嘉士伯等品牌在高端市场持续鏖战&#xff0c;实际成果如何也可以从业绩一探究竟。 以百威亚太为例。8月3日&#xff0c;百威亚太发布2023年上半年…

记录一次electron打包提示文件找不到的解决方法

没有配置files选项 files的作用是配置打包到应用程序的构建资源 就是说如果你想使用项目那个目录下的文件 就得通过files配置一下不然就会报错 json文件或者yml文件会报的错 格式是这样的 "files": ["dist-electron", "dist"],electron打包配…

【C++学习】STL容器——list

目录 一、list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list 迭代器失效 二、list的模拟实现 2.1 模拟实现list 三、list和vector的对比…

【算法挨揍日记】day01——双指针算法_移动零、 复写零

283.移动零 283. 移动零https://leetcode.cn/problems/move-zeroes/ 题目&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 …

生信豆芽菜-火山图绘制使用说明

网站&#xff1a;http://www.sxdyc.com/visualsVolcano 一、火山图简介 火山图是散点图的一种&#xff0c;它将统计测试中的统计显著性量度&#xff08;如p value&#xff09;和变化幅度&#xff08;logFC&#xff09;相结合&#xff0c;能够快速直观地识别那些变化幅度较大且具…

13个Python最佳编程技巧,越早知道越好

每天我们都会面临许多需要高级编码的编程挑战。你不能用简单的 Python 基本语法来解决这些问题。在本文中&#xff0c;我将分享 13 个高级 Python 脚本&#xff0c;它们可以成为你项目中的便捷工具。如果你目前还用不到这些脚本&#xff0c;你可以先添加收藏&#xff0c;以备留…

springMVC 程序开发

目录 一. 认识 springMVC spring&#xff0c;springBoot&#xff0c;springMVC的关系 二. springMVC 的连接和获取参数 1. 注解分析&#xff08;不带参数&#xff09; 2. 获取参数 3. 获取对象参数 4. 重命名功能 5. 获取 JSON 对象 6. 通过 path 文件路径来传递参数…

新版Android Studio模拟器浮动

&#xff08;水一篇&#xff0c;但其实很多入门同学不知道&#xff09; 安装新版Andorid Studio后会发现模拟器是内嵌在AS中的&#xff0c;如何让她浮动

[C++项目] Boost文档 站内搜索引擎(4): 搜索的相关接口的实现、线程安全的单例index接口、cppjieba分词库的使用、综合调试...

有关Boost文档搜索引擎的项目的前三篇文章, 已经分别介绍分析了: 项目背景: &#x1fae6;[C项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍…文档解析、处理模块parser的实现: &#x1fae6;[C项目] Boost文档 站内搜索引擎(2): 文档文本解析模块…

C++学习| MFC简单入门

前言&#xff1a;因为接手了CMFC的程序&#xff0c;所以需要对MFC编程方面有所了解。 C之MFC简单入门 MFC相关的概念MFCWIN32QT MFC项目基本操作MFC项目创建MFC项目文件解读界面和代码数据交互——加法器 MFC相关的概念 MFC MFC&#xff08;Microsoft Foundation Classes微软…