前言
最近有个朋友, 刚入职没多久就被组长叼了, 原因是他在业务场景中开Goroutine导致测试服务器资源占用过大, 其他服务都崩了…
场景类似于监听区块链交易, 对每个区块进行轮询处理每笔交易, 他直接循环开Goroutine处理每笔交易, 数据大了goroutine开的太多导致资源占用过大, 导致了这场悲剧;
工作中我们需要开Goroutine来提高代码处理的效率, 但也不能滥用, 需要对它进行一定限制, 保证资源占用在可控范围内, 所以我们需要对项目中Goroutine的数量进行限制, 用channel就可以很好的做到;
正文
直接上代码
gopool
package gopool import "sync" type Pool struct { wg sync.WaitGroup queue chan struct{} } // NewGoPool 实例化一个go程池 func NewGoPool(i int) *Pool { if i < 1 { i = 1 } return &Pool{queue: make(chan struct{}, i)} } // Add 添加 func (p *Pool) Add() { p.queue <- struct{}{} p.wg.Add(1) } // Done 释放 func (p *Pool) Done() { p.wg.Done() <-p.queue } // Wait 等待 func (p *Pool) Wait() { p.wg.Wait() }
test
package gopool import ( "fmt" "runtime" "testing" "time" ) func TestNewGoPool(t *testing.T) { defaultNum := runtime.NumGoroutine() p := NewGoPool(2) for i := 0; i < 100; i++ { p.Add() go func() { defer p.Done() time.Sleep(1 * time.Second) fmt.Println("go routine num: ", runtime.NumGoroutine()-defaultNum) }() } p.Wait() fmt.Println("go routine num: ", runtime.NumGoroutine()) }
代码都在我的个人项目 fly 中, 里面封装了一些常用的组件和应用示例, 欢迎大家 star / 提 Issues;
项目瓶颈期了…