-
-
Notifications
You must be signed in to change notification settings - Fork 217
Open
Labels
Description
现象:
当有较多的goroutine在等待从Pool中Get连接,同时没有空闲连接时,有种情况,当被使用的连接,同时出错并被调用者Close掉时,等待获取连接的goroutine会一直阻塞等待从connReq这个channel获取连接,而所有的连接都已经被关闭了,不会再有可用的连接,导致一直等待,程序hang住。
原因
在Get方法中,第133行检查完已创建的连接数达到了最大值后,会等待从connReq的channel等待其它goroutine Put回来的连接。
在Close方法中,会把openingConns--,但已经没法触发Get方法去新建连接了,Get方法都被阻塞在从connReq的channel拿连接了。
Get方法133行
Line 133 in 58e025e
| if c.openingConns >= c.maxActive { |
Lines 130 to 140 in 58e025e
| default: | |
| c.mu.Lock() | |
| log.Debugf("openConn %v %v", c.openingConns, c.maxActive) | |
| if c.openingConns >= c.maxActive { | |
| req := make(chan connReq, 1) | |
| c.connReqs = append(c.connReqs, req) | |
| c.mu.Unlock() | |
| ret, ok := <-req | |
| if !ok { | |
| return nil, ErrMaxActiveConnReached | |
| } |
Close方法
Lines 202 to 213 in 58e025e
| func (c *channelPool) Close(conn interface{}) error { | |
| if conn == nil { | |
| return errors.New("connection is nil. rejecting") | |
| } | |
| c.mu.Lock() | |
| defer c.mu.Unlock() | |
| if c.close == nil { | |
| return nil | |
| } | |
| c.openingConns-- | |
| return c.close(conn) | |
| } |