摘要
channel
引入-并发编程时遇到问题
socket: too many open files
linux
channel
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:n err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:t err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:v err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:l err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:s err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:h err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:r err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
2022-05-30T15:21:50.624+0800 ERROR project_manage/organization_service.go:156 func:GetProjectSimpleList GetStaffBaseInfoApi engName:g err:Get "http://xxx": dial tcp x.xx.xx.xx:80: socket: too many open files
使用channel限制并发数
channelchannel
基本逻辑如下:
channelchannelchannelchannel
此方法原理简单,代码实现起来也简单,十分优雅。不过需要注意的是,在最大并发数未触及其他限制的情况下(比如上述的同时请求数量太多,进程打开的句柄数量受限等情况),最大并发数也并不是越多,程序执行的越快,关于这个问题的讨论后续可以再写一篇文章进行深入。
具体Go代码如下所示:
func GetInfo(idList []int) error {
var wg sync.WaitGroup
// 限制最大并发数为100
limitGoroutine := make(chan int, 100)
wg.Add(len(idList))
for _, id := range idList {
// 每启动一个协程,就往channel里写入一位数
limitGoroutine <- 0
go func() {
// 并发请求获取信息
// 存入数据库
wg.Done()
// 协程执行完退出时,就从channel里读一位数
<-limitGoroutine
}()
}
wg.Wait()
return nil
}