gitee.com/quant1x/gox@v1.7.6/pool/channel.go (about) 1 package pool 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 "time" 8 ) 9 10 var ( 11 //ErrMaxActiveConnReached 连接池超限 12 ErrMaxActiveConnReached = errors.New("MaxActiveConnReached") 13 ) 14 15 // Config 连接池相关配置 16 type Config struct { 17 //连接池中拥有的最小连接数 18 InitialCap int 19 //最大并发存活连接数 20 MaxCap int 21 //最大空闲连接 22 MaxIdle int 23 //生成连接的方法 24 Factory func() (interface{}, error) 25 //关闭连接的方法 26 Close func(interface{}) error 27 //检查连接是否有效的方法 28 Ping func(interface{}) error 29 //连接最大空闲时间,超过该事件则将失效 30 IdleTimeout time.Duration 31 } 32 33 type connReq struct { 34 idleConn *idleConn 35 } 36 37 // channelPool 存放连接信息 38 type channelPool struct { 39 mu sync.RWMutex 40 conns chan *idleConn 41 factory func() (interface{}, error) 42 close func(interface{}) error 43 ping func(interface{}) error 44 idleTimeout, waitTimeOut time.Duration 45 maxActive int 46 openingConns int 47 connReqs []chan connReq 48 } 49 50 type idleConn struct { 51 conn interface{} 52 t time.Time 53 } 54 55 // NewChannelPool 初始化连接 56 func NewChannelPool(poolConfig *Config) (Pool, error) { 57 if !(poolConfig.InitialCap <= poolConfig.MaxIdle && poolConfig.MaxCap >= poolConfig.MaxIdle && poolConfig.InitialCap >= 0) { 58 return nil, errors.New("invalid capacity settings") 59 } 60 if poolConfig.Factory == nil { 61 return nil, errors.New("invalid factory func settings") 62 } 63 if poolConfig.Close == nil { 64 return nil, errors.New("invalid close func settings") 65 } 66 67 c := &channelPool{ 68 conns: make(chan *idleConn, poolConfig.MaxIdle), 69 factory: poolConfig.Factory, 70 close: poolConfig.Close, 71 idleTimeout: poolConfig.IdleTimeout, 72 maxActive: poolConfig.MaxCap, 73 openingConns: poolConfig.InitialCap, 74 } 75 76 if poolConfig.Ping != nil { 77 c.ping = poolConfig.Ping 78 } 79 80 for i := 0; i < poolConfig.InitialCap; i++ { 81 conn, err := c.factory() 82 if err != nil { 83 c.Release() 84 return nil, fmt.Errorf("factory is not able to fill the pool: %s", err) 85 } 86 c.conns <- &idleConn{conn: conn, t: time.Now()} 87 } 88 89 return c, nil 90 } 91 92 // getConns 获取所有连接 93 func (c *channelPool) getConns() chan *idleConn { 94 c.mu.Lock() 95 conns := c.conns 96 c.mu.Unlock() 97 return conns 98 } 99 100 // Get 从pool中取一个连接 101 func (c *channelPool) Get() (interface{}, error) { 102 conns := c.getConns() 103 if conns == nil { 104 return nil, ErrClosed 105 } 106 for { 107 select { 108 case wrapConn := <-conns: 109 if wrapConn == nil { 110 return nil, ErrClosed 111 } 112 //判断是否超时,超时则丢弃 113 if timeout := c.idleTimeout; timeout > 0 { 114 if wrapConn.t.Add(timeout).Before(time.Now()) { 115 //丢弃并关闭该连接 116 _ = c.Close(wrapConn.conn) 117 continue 118 } 119 } 120 //判断是否失效,失效则丢弃,如果用户没有设定 ping 方法,就不检查 121 if c.ping != nil { 122 if err := c.Ping(wrapConn.conn); err != nil { 123 _ = c.Close(wrapConn.conn) 124 continue 125 } 126 } 127 return wrapConn.conn, nil 128 default: 129 c.mu.Lock() 130 //log.Debugf("openConn %v %v", c.openingConns, c.maxActive) 131 if c.openingConns >= c.maxActive { 132 req := make(chan connReq, 1) 133 c.connReqs = append(c.connReqs, req) 134 c.mu.Unlock() 135 ret, ok := <-req 136 if !ok { 137 return nil, ErrMaxActiveConnReached 138 } 139 if timeout := c.idleTimeout; timeout > 0 { 140 if ret.idleConn.t.Add(timeout).Before(time.Now()) { 141 //丢弃并关闭该连接 142 _ = c.Close(ret.idleConn.conn) 143 continue 144 } 145 } 146 return ret.idleConn.conn, nil 147 } 148 if c.factory == nil { 149 c.mu.Unlock() 150 return nil, ErrClosed 151 } 152 conn, err := c.factory() 153 if err != nil { 154 c.mu.Unlock() 155 return nil, err 156 } 157 c.openingConns++ 158 c.mu.Unlock() 159 return conn, nil 160 } 161 } 162 } 163 164 // Put 将连接放回pool中 165 func (c *channelPool) Put(conn interface{}) error { 166 if conn == nil { 167 return errors.New("connection is nil. rejecting") 168 } 169 170 c.mu.Lock() 171 172 if c.conns == nil { 173 c.mu.Unlock() 174 return c.Close(conn) 175 } 176 177 if l := len(c.connReqs); l > 0 { 178 req := c.connReqs[0] 179 copy(c.connReqs, c.connReqs[1:]) 180 c.connReqs = c.connReqs[:l-1] 181 req <- connReq{ 182 idleConn: &idleConn{conn: conn, t: time.Now()}, 183 } 184 c.mu.Unlock() 185 return nil 186 } else { 187 select { 188 case c.conns <- &idleConn{conn: conn, t: time.Now()}: 189 c.mu.Unlock() 190 return nil 191 default: 192 c.mu.Unlock() 193 //连接池已满,直接关闭该连接 194 return c.Close(conn) 195 } 196 } 197 } 198 199 // Close 关闭单条连接 200 func (c *channelPool) Close(conn interface{}) error { 201 if conn == nil { 202 return errors.New("connection is nil. rejecting") 203 } 204 c.mu.Lock() 205 defer c.mu.Unlock() 206 if c.close == nil { 207 return nil 208 } 209 c.openingConns-- 210 return c.close(conn) 211 } 212 213 // Ping 检查单条连接是否有效 214 func (c *channelPool) Ping(conn interface{}) error { 215 if conn == nil { 216 return errors.New("connection is nil. rejecting") 217 } 218 return c.ping(conn) 219 } 220 221 // Release 释放连接池中所有连接 222 func (c *channelPool) Release() { 223 c.mu.Lock() 224 conns := c.conns 225 c.conns = nil 226 c.factory = nil 227 c.ping = nil 228 closeFun := c.close 229 c.close = nil 230 c.mu.Unlock() 231 232 if conns == nil { 233 return 234 } 235 236 close(conns) 237 for wrapConn := range conns { 238 //log.Printf("Type %v\n",reflect.TypeOf(wrapConn.conn)) 239 _ = closeFun(wrapConn.conn) 240 } 241 } 242 243 // Len 连接池中已有的连接 244 func (c *channelPool) Len() int { 245 return len(c.getConns()) 246 }