https://github.com/panjf2000/ants
1.1 什么是 ants
ants
是一個高性能的 Go 語言 goroutine 池,它能復用已完成任務的 goroutine,避免頻繁創建和銷毀 goroutine,節省 CPU 與內存開銷,并且能限制并發數量防止資源被耗盡。
1.2 安裝
go get -u github.com/panjf2000/ants/v2
1.3 最簡單的例子
package mainimport ("fmt""time""github.com/panjf2000/ants/v2"
)func main() {// 創建一個容量為 10 的 goroutine 池pool, _ := ants.NewPool(10)defer pool.Release() // 程序結束釋放資源// 提交任務for i := 0; i < 20; i++ {n := i_ = pool.Submit(func() {fmt.Printf("Task %d running\n", n)time.Sleep(time.Second)})}fmt.Println("All tasks submitted")time.Sleep(3 * time.Second) // 等待任務執行完
}
特點:
- 同時最多只有 10 個任務運行。
- 其余任務排隊等待空閑 worker。
2. 進階篇
2.1 核心 API
方法 | 作用 |
---|---|
ants.NewPool(size, options...) | 創建一個普通任務池 |
ants.NewPoolWithFunc(size, func, options...) | 創建一個綁定任務處理函數的池 |
Submit(task) | 提交任務到池 |
Invoke(param) | 提交參數,調用綁定函數 |
Running() | 當前正在運行的 worker 數量 |
Free() | 當前空閑 worker 數量 |
Cap() | 池容量 |
Tune(size) | 動態調整容量 |
Release() | 釋放所有資源 |
Reboot() | 重啟一個已釋放的池 |
2.2 常用配置項
ants.WithPreAlloc(true) // 預先分配內存,減少運行時分配
ants.WithNonblocking(true) // worker 不夠時立即返回錯誤,而不是等待
ants.WithMaxBlockingTasks(1000) // 最大等待任務數
ants.WithPanicHandler(func(err interface{}) {fmt.Println("panic:", err) // 捕獲任務中的 panic
})
ants.WithExpiryDuration(time.Second * 10) // 空閑 worker 過期時間
2.3 PoolWithFunc
用法
package mainimport ("fmt""github.com/panjf2000/ants/v2""time"
)func main() {// 定義處理函數handler := func(data interface{}) {fmt.Printf("Processing: %v\n", data)time.Sleep(time.Millisecond * 500)}// 創建綁定函數的池pool, _ := ants.NewPoolWithFunc(5, handler)defer pool.Release()for i := 0; i < 10; i++ {_ = pool.Invoke(i) // 直接傳參數}
}
3. 實戰篇
3.1 批量任務執行
場景:你需要批量處理 10000 條數據,但不希望一次性開 10000 個 goroutine。
package mainimport ("fmt""sync""time""github.com/panjf2000/ants/v2"
)func processTask(id int) {fmt.Printf("Task %d start\n", id)time.Sleep(time.Second)fmt.Printf("Task %d done\n", id)
}func main() {var wg sync.WaitGrouppool, _ := ants.NewPool(50) // 控制并發為 50defer pool.Release()for i := 0; i < 10000; i++ {wg.Add(1)taskID := i_ = pool.Submit(func() {defer wg.Done()processTask(taskID)})}wg.Wait()
}
3.2 HTTP 并發控制
爬取多個 URL,但限制同時請求的數量。
package mainimport ("fmt""net/http""sync""github.com/panjf2000/ants/v2"
)func fetch(url string) {resp, err := http.Get(url)if err != nil {fmt.Println(err)return}defer resp.Body.Close()fmt.Println(url, resp.StatusCode)
}func main() {urls := []string{"https://golang.org","https://github.com","https://google.com",}var wg sync.WaitGrouppool, _ := ants.NewPool(5)defer pool.Release()for _, url := range urls {wg.Add(1)u := url_ = pool.Submit(func() {defer wg.Done()fetch(u)})}wg.Wait()
}
4. 最佳實踐與注意事項
-
適合長時間運行的服務
- 在任務密集的服務中能顯著降低內存占用。
-
任務不宜過大或阻塞太久
- 單個任務阻塞會占用 worker,影響吞吐量。
-
panic 處理必須配置
- 避免單個任務導致池崩潰。
-
選擇合適的池大小
- 一般為
CPU核數 * N
,N 根據 IO 密集度調整。
- 一般為
-
性能對比
- 對于少量任務,直接開 goroutine 可能更快;
- 對于大規模并發,
ants
會明顯減少 GC 壓力。