首页 > 其他分享 >ants:强大的高性能与低成本 Go 协程池

ants:强大的高性能与低成本 Go 协程池

时间:2024-06-16 12:59:16浏览次数:21  
标签:并发 fmt ants 协程池 任务 func Go

ants:强大的高性能与低成本 Go 协程池

原创 K8sCat 源自开发者 2024-06-16 11:28 广东 听全文 源自开发者 专注于提供关于Go语言的实用教程、案例分析、最新趋势,以及云原生技术的深度解析和实践经验分享。 256篇原创内容 公众号

在开发高并发程序时,管理并发的能力至关重要。在 Golang 中,虽然可以使用 Go 内置的 goroutines 来处理并发任务,但没有调度和控制的 goroutine 很容易导致系统资源耗尽。为了解决这个问题,ants 是一个高性能且低成本的 Go 协程池库,可以更高效地管理和使用 goroutine。

本文将详细介绍如何使用 ants 作为 goroutine 池来优化 Go 应用程序,包括如何安装 ants、创建池、提交任务、调整参数等,并通过几个示例演示其实际应用。

安装 ants

首先,我们需要在项目中安装 ants。这可以通过以下命令完成:

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

安装完成后,就可以在代码中引用 ants 了。

基本使用方法

基本的使用 ants 非常简单。我们可以创建一个 goroutine 池,在池中提交任务,然后关闭池。以下是一个简单的示例:

package main

import (
    "fmt"
    "time"
    "github.com/panjf2000/ants/v2"
)

func main() {
    runTask := func(i interface{}) {
        fmt.Printf("Running task: %d\n", i.(int))
        time.Sleep(1 * time.Second) // 模拟任务处理
    }

    // 创建一个具有 10 个 goroutines 的池
    p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
        runTask(i)
    })
    defer p.Release()

    // 提交任务
    for i := 0; i < 30; i++ {
        _ = p.Invoke(i)
    }

    // 等待所有任务完成
    p.Wait()
    fmt.Println("All tasks completed")
}

在这个示例中,我们创建了一个包含 10 个 goroutines 的池,并提交了 30 个任务。ants 会自动调度这些任务,确保并发数不会超过池的大小。

调整参数

ants 提供了多种参数来优化池的行为。例如,可以调整池的大小、设置非阻塞模式、以及设置空闲的超时时间等。

设置池大小

我们可以创建一个不同大小的池,通过 NewPoolWithFunc 来指定池大小:

p, _ := ants.NewPoolWithFunc(20, func(i interface{}) {
    runTask(i)
})

设置非阻塞模式

默认情况下,如果池已满,新任务会阻塞直到有空闲 goroutine 可用。我们可以通过设置非阻塞模式来改变这一行为:

p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
    runTask(i)
}, ants.WithNonblocking(true))

在非阻塞模式下,如果池已满,新任务会立即返回错误,而不是等待。

设置任务超时

我们还可以设置池中任务的超时时间,以避免某些任务耗时过长:

p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
    runTask(i)
}, ants.WithExpireDuration(5 * time.Second))

在这个示例中,每个任务最多只能运行 5 秒钟,超过这个时间,任务将被自动终止。

示例:网络爬虫

假设我们正在编写一个网络爬虫,需要并发访问多个网页。可以使用 ants 来管理并发连接:

package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
    "github.com/panjf2000/ants/v2"
)

func main() {
    urls := []string{
        "http://example.com",
        "http://example.org",
        "http://example.net",
    }

    fetchURL := func(url string) {
        resp, err := http.Get(url)
        if err != nil {
            fmt.Printf("Failed to fetch %s: %s\n", url, err)
            return
        }
        defer resp.Body.Close()
        body, _ := ioutil.ReadAll(resp.Body)
        fmt.Printf("Fetched from %s: %d bytes\n", url, len(body))
    }

    p, _ := ants.NewPoolWithFunc(5, func(i interface{}) {
        fetchURL(i.(string))
    })
    defer p.Release()

    for _, url := range urls {
        _ = p.Invoke(url)
    }

    p.Wait()
    fmt.Println("All URLs fetched")
}

在这个示例中,我们创建了一个网络爬虫,使用 ants 来并发地访问多个网页。爬虫只使用 5 个 goroutines,并发访问多个 URL。

扩展思路

除了基本的任务提交和参数调整,还有许多高级用法。下面列举几个:

动态调整池大小

有时候,我们需要根据运行时环境动态调整池的大小。ants 支持在运行时调整池大小:

pool.Tune(20)

性能监控

ants 内置了一些性能监控功能,可以用来观察池的运行状态:

fmt.Printf("Running goroutines: %d\n", pool.Running())
fmt.Printf("Free goroutines: %d\n", pool.Free())

异常处理

可以为每个任务设置异常处理机制,确保 goroutine 不会因为 panic 而崩溃:

p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic", r)
        }
    }()
    runTask(i)
})

总结

使用 ants 可以显著提高 Go 应用程序的并发能力,使得 goroutines 的管理更加高效和可靠。通过调整参数,我们可以更灵活地控制池的行为,以满足不同的应用场景需求。无论是简单的并发任务,还是复杂的并发控制,ants 都提供了强大的支持。

希望通过本文,你能够对 ants 有一个全面的理解,并能在实际项目中灵活运用。

标签:并发,fmt,ants,协程池,任务,func,Go
From: https://www.cnblogs.com/cheyunhua/p/18250502

相关文章

  • (高清pdf)UNIX环境高级编程 (W. Richard Stevens, Stephen A. Rago)
    书:pan.baidu.com/s/1tIHXj9HmIYojAHqje09DTA?pwd=jqso提取码:jqsoUNIX系统概述:介绍UNIX操作系统的基本组成、特点和发展历程,为读者后续的学习打下基础。文件和目录操作:详细讲解文件和目录的创建、打开、读写、关闭等操作,以及文件属性的获取和设置。进程管理:深入剖析进程的创建......
  • Ubuntu安装Golang环境
    一、安装使用apt安装更新包列表:sudoaptupdate**安装Golang**:sudoaptinstallgolang验证安装:执行以下命令来检查是否成功安装了Go:goversion输出结果:goversiongo1.21.1linux/amd64二、配置环境设置GOPATH环境变量(可选,但建议):GOPATH是Go......
  • golang 所有关键字的列表及释义归类
    golang所有关键字的列表及释义归类,截至1.18版本。 [控制结构]if :条件语句,基于布尔表达式的值决定是否执行特定的代码块。else、elseif   :用在if语句之后,当条件表达式为假时执行的代码块。switch:多路选择语句,根据不同的情况执行不同......
  • golang net 包的功能概述
     Go语言中的net包提供了一个可移植的网络输入输出接口,涵盖了TCP/IP、UDP、域名解析以及Unix域套接字等功能。该包提供了访问底层网络原语的能力,但大多数客户端仅需使用基本接口,这包括Dial、Listen和Accept函数以及相关的Conn和Listener接口。crypto/tls包也利用......
  • Tropical Plants | 改进的日本晴单倍型基因组UQ_NIP
    昆士兰大学RobertJ.Henry教授团队利用改进的单倍型水平基因组组装揭示更多的水稻基因。本研究利用更准确的测序技术,分析组装了一个改进的单倍型水平水稻基因组。该改进的基因组组装包含了早期基因组序列中缺失的区域,并且基于更高的序列准确性注释了3000多个新的基因。这个单倍......
  • goaccess分析nginx日志详解
    goaccess version:1.9安装方式:源文件makemakeinstall 执行环境:cli完整access.log:192.168.1.3:16423|240e:42c:1b30:111:b4c1:49ff:fe49:392c,113.96.59.2114/Jun/2024:00:01:15+0800HTTP/1.0GEThttp://www.baidu.com/yl/ysj/dsj/folder1088/?imageView/......
  • django中orm的使用
    Orm是django连接mysql数据库的工具,用户可以通过orm实现对数据库的增删改查。1.启动mysql创建数据库在cmd中输入mysql-uroot-p后再输入密码运行mysql然后创建数据库:createdatabase数据库名DEFAULTCHARSETutf8COLLATEutf8_general_ci;2让django链接数据库在setting......
  • 【go】【grpc】【interceptor】
    @目录写在前面客户端unaryinterceptor服务器nuaryinterceptor客户端streaminterceptor服务器streaminterceptor服务器多unayinterceptor具体例子服务器unaryinterceptor多拦截器参考资料基础/标准库/第三方库golang导航编程规范算法|面试项目写在前面相关博文个......
  • Golang 百题(实战快速掌握语法)_1
    整形转字符串类型实验介绍本实验将展示三种方法来实现整形类型转字符串类型。知识点strconvfmtItoa函数代码实例Go语言中strconv包的itoa函数输入一个int类型,返回转换后的字符串。下面是一个例子。packagemainimport("fmt""strconv")funcmai......
  • WebGoC题解(4) 115.第5题 同心圆(比赛模拟题)
    题目描述学校准备在颁奖会把这次比赛的前10名的成绩用崭新的形状表示出来,这个艰巨的任务交给了小C。为了和以往不同,小C决定用每个学生的成绩作为半径画同心圆来表示。这个创新的举动需要你使用GoC编程,在一个黑色实心圆背景下,用10个红色圆表示成绩。具体形状参见输入输出样例......