摘要

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
}