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 main

import (
	"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 := 1000
	var wg sync.WaitGroup
	syncCalculateSum := 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 main

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

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

var sum int32

func 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 并发模型有较深的理解,对相关领域感兴趣的开发者可以进行参考学习。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在校外连接校内实验室服务器

zerotier 内网穿透 一、zerotier的操作 去官网注册、登录、创建网络 zerotier官网 我使用微软账号登录的&#xff0c;这个随便 点 Create A Network NETWORK ID点ID进去 二、服务器(校内)上的操作 1. Ubuntu配置SSH 如果出现不在sudoers列表的问题查看这里 sudo apt …

Signal Desktop for Mac(专业加密通讯软件)中文版安装教程

想让您的聊天信息更安全和隐藏吗&#xff1f; Mac版本的Signal Desktop是MACOS上的专业加密通信工具&#xff0c;非常安全。使用信号协议&#xff0c;该协议结合了固定前密钥&#xff0c;双重RATCHES算法和3-DH握手信号&#xff0c;该信号可以确保第三方实体将不会传达您的消息…

Telink泰凌微TLSR8258蓝牙开发笔记(一)

一、开发环境搭建 1.1、软件开发环境&#xff1a; 1.1.1、开发的IDE&#xff1a; IDE下载链接 1.1.2、烧录工具 DBT下载地址 1.1.3、蓝牙SDK 蓝牙SDK下载地址 1.2、硬件开发环境 8258开发板烧录工具一套 二、运行例程&#xff0c;并使能打印调试信息功能 File-->Impo…

广州VR制作 | 利用VR元宇宙平台开展林地管理培训的优势

在林业领域&#xff0c;实地调查是获取准确数据和深入了解森林生态的重要手段。然而&#xff0c;传统的实地调查方法存在诸多问题&#xff0c;如时间成本高、人力物力投入大、安全风险高等。为了解决这些教学痛点&#xff0c;我们引入了虚拟现实(VR)技术&#xff0c;通过虚拟林…

【果树农药喷洒机器人】Part5:基于深度相机与分割掩膜的果树冠层体积探测方法

文章目录 一、引言二、树冠体积测量对比方法2.1冠层体积人工测量法2.2冠层体积拟合测量法 三、基于深度相机与分割掩膜探测树冠体积方法3.1像素值与深度值的转换3.2树冠体积视觉探测法3.3实验分析 总结 一、引言 果树靶标探测是实现农药精准喷施的关键环节&#xff0c;本章以果…

编码技巧——Sentinel的blockHandler与fallback

本文介绍Sentinel的blockHandler与fallback的区别&#xff0c;背景是&#xff1a;发生限流时&#xff0c;配置的sentinel的blockhandler没有生效而fallback生效了&#xff1b;排查原因&#xff0c;从而给出Sentinel配置异常降级和限流降级的代码写法&#xff1b; 在查看源码前…

记录问题: servlet获取项目包绝对路径

【2023-8-8 23:46:27 星期二】 如何获取在webapp下的路径?而不是target包下的webapp目录 比如这里应该获取到 F:\Tiam\Desktop\freemarker\freemarker-demo01\src\main\webapp 而readPath总是获取到 F:\Tiam\Desktop\freemarker\freemarker-demo01\target\freemarker-demo0…

体验自制免费开源闯关学SQL

文章目录 前言mac安装nodejs启动体验 前言 sql是常用必不可少的一种语言&#xff0c;我们都或有各种各样的学习经历&#xff0c;最近看鱼皮大佬开源了一款自制的闯关学SQL项目&#xff0c;该项目是纯前端语言&#xff0c;不需要太多依赖以及前置知识&#xff0c;直接下载就可以…

事务,不只ACID | 京东物流技术团队

1. 什么是事务&#xff1f; 应用在运行时可能会发生数据库、硬件的故障&#xff0c;应用与数据库的网络连接断开或多个客户端端并发修改数据导致预期之外的数据覆盖问题&#xff0c;为了提高应用的可靠性和数据的一致性&#xff0c;事务应运而生。 从概念上讲&#xff0c;事务…

使用langchain与你自己的数据对话(五):聊天机器人

之前我已经完成了使用langchain与你自己的数据对话的前四篇博客&#xff0c;还没有阅读这四篇博客的朋友可以先阅读一下&#xff1a; 使用langchain与你自己的数据对话(一)&#xff1a;文档加载与切割使用langchain与你自己的数据对话(二)&#xff1a;向量存储与嵌入使用langc…

常用开源的弱口令检查审计工具

常用开源的弱口令检查审计工具 1、SNETCracker 1.1、超级弱口令检查工具 SNETCracker超级弱口令检查工具是一款开源的Windows平台的弱口令安全审计工具&#xff0c;支持批量多线程检查&#xff0c;可快速发现弱密码、弱口令账号&#xff0c;密码支持和用户名结合进行检查&am…

DLA 神经网络的极限训练方法:gradient checkpointing

gradient checkpointing 一般来说&#xff0c;训练的过程需要保存中间结果&#xff08;不管是GPU还是CPU&#xff09;。前向传播根据输入(bottom_data)计算输出(top_data)&#xff0c;后向传播由top_diff计算bottom_diff&#xff08;如果某个变量打开梯度进行训练的话&#xff…

python实现对图油画、卡通、梦幻、草图、水彩效果

本篇博客将介绍如何使用wxPython模块和OpenCV库来实现对图像进行灰度化、二值化、伽马校正、色彩空间转换和图像反转这5种效果的合并程序。程序可以通过wxPython提供的GUI界面来选择图片路径和效果类型&#xff0c;程序会将处理后的图像保存到指定路径并打开。 步骤一&#xf…

Java-对对象的拷贝、抽象类和接口的区别、Object类、对象的比较方法和内部类

目录 1.Clonable接口和深拷贝 2.抽象类和接口的区别 3.Object类 4.获取对象的信息 5.对象比较方法equals 6.内部类 1.Clonable接口和深拷贝 Java 中内置了一些很有用的接口, Clonable 就是其中之一&#xff0c;Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对…

jupyter lab build失败,提示需要安装版本>=12.0.0的nodejs但其实已从官网安装18.17.0版本 的解决方法

出现的问题如题目所示&#xff0c;这个问题差点要把我搞死了。。。但还是在没有重装的情况下解决了&#x1f618;。 问题来源 初衷是想安装lsp扩展&#xff0c;直接在jupyter lab网页界面的extensions中搜索lsp并点击install krassowski/jupyterlab-lsp&#xff0c;会提示需要…

tomcat虚拟主机配置演示

一.新建用于显示的index.jsp文件&#xff0c;写入内容 二.修改tomcat/apache-tomcat-8.5.70/conf/server.xml配置文件 匹配到Host那部分&#xff0c;按上面格式在后面添加自己的域名和文件目录信息 主要是修改name和docBase 保存退出重启tomcat&#xff0c;确保tomcat运行…

QT笔记——QT自定义事件

我们有时候想发送自定义事件 1&#xff1a;创建自定义事件&#xff0c;首先我们需要知道它的条件 1&#xff1a;自定义事件需要继承QEvent 2&#xff1a;事件的类型需要在 QEvent::User 和 QEvent::MaxUser 范围之间&#xff0c;在QEvent::User之前 是预留给系统的事件 3&#…

python免费下载安装教程,python编程软件 免安装

本篇文章给大家谈谈python免费下载安装教程&#xff0c;以及python编程软件 免安装&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 百度网盘 请输入提取码 提取码: wifx 下载好记得把python文件解压&#xff0c;里面有32位和64位的&#xff0c;根据自己配置…

【工作中问题解决实践 十】一次内存泄露排查-MAT使用指南

最近体验了一把当医生的感觉&#xff0c;定位病根病因&#xff0c;感觉这种要揪出问题的感觉很爽&#xff0c;并不觉得麻烦&#xff0c;这里将整个排查过程记录一下&#xff0c;方便之后再遇到类似问题有应对之道。 问题背景 2023-07-18 早上还在睡梦中的俺被一条条报警消息铛…

Spring事务管理

1.什么是事务 数据库事务是指作为单个逻辑工作单元执行的一系列操作&#xff0c;这些操作要么一起成功&#xff0c;要么一起失败&#xff0c;是一个不可分割的工作单元。 涉及到事务的场景非常多&#xff0c;一个 service 中往往需要调用不同的 dao 层方法&#xff0c;这些方法…