redigo提示connection pool exhausted
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc
1. 引言
线上的某个服务(Golang开发)使用Redis作为消息队列,使用的redis库是garyburd/redigo, 这两天出现如下错误
connection pool exhausted
2. 产生原因
阅读源码pool.go 阅读get()即可
type Pool struct {
// Dial()方法返回一个连接,从在需要创建连接到的时候调用
Dial func() (Conn, error)
// TestOnBorrow()方法是一个可选项,该方法用来诊断一个连接的健康状态
TestOnBorrow func(c Conn, t time.Time) error
// 最大空闲连接数
MaxIdle int
// 一个pool所能分配的最大的连接数目
// 当设置成0的时候,该pool连接数没有限制
MaxActive int
// 空闲连接超时时间,超过超时时间的空闲连接会被关闭。
// 如果设置成0,空闲连接将不会被关闭
// 应该设置一个比redis服务端超时时间更短的时间
IdleTimeout time.Duration
// 如果Wait被设置成true,则Get()方法将会阻塞
Wait bool
... ...
}
以上异常的原因是这样的,在garyburd/redigo中,得到连接的步骤如下
1. 尝试从空闲列表中,获得一个可用连接;如果成功直接返回,失败则尝试步骤2
2. 如果当前的Active 连接数 < MaxActive,则尝试创建一个新连接;如果成功直接返回,失败则尝试步骤3
3. 判断Wait为true则等待,否则报出异常
// ErrPoolExhausted is returned from a pool connection method (Do, Send,
// Receive, Flush, Err) when the maximum number of database connections in the
// pool has been reached.
var ErrPoolExhausted = errors.New("redigo: connection pool exhausted")
3. 解决方法
- 1) 设置MaxActive,设MaxActive=0(表示无限大)或者足够大。
- 2) 设置Wait=true,当程序执行get(),无法获得可用连接时,将会暂时阻塞。
4. 完整的初始化连接池的代码
func NewRedisPool(redisConf context.RedisConf) *redis.Pool {
address := fmt.Sprintf("%v:%v", redisConf.Host, redisConf.Port)
dbOption := redis.DialDatabase(redisConf.Db)
pwOption := redis.DialPassword(redisConf.Password)
// **重要** 设置读写超时
readTimeout := redis.DialReadTimeout(time.Second * time.Duration(redisConf.ConTimeout))
writeTimeout := redis.DialWriteTimeout(time.Second * time.Duration(redisConf.ConTimeout))
conTimeout := redis.DialConnectTimeout(time.Second * time.Duration(redisConf.ConTimeout))
redisPool := &redis.Pool{
// 从配置文件获取maxidle以及maxactive,取不到则用后面的默认值
MaxIdle: redisConf.MaxIdleConn,
MaxActive: redisConf.MaxActiveConn,
// **重要** 如果空闲列表中没有可用的连接
// 且当前Active连接数 < MaxActive
// 则等待
Wait: true,
IdleTimeout: time.Duration(redisConf.IdleTimeout) * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", address, dbOption, pwOption,
readTimeout, writeTimeout, conTimeout)
if err != nil {
return nil, err
}
return c, nil
},
}
return redisPool
}