在大多数实际业务场景中,为满足高并发的需求,往往需要提供连接池的支持,包括连接池的管理,连接的创建、销毁等等,还要保证并发安全。实现如下:
package client
import (
"errors"
"net"
"sync"
"protocol"
)
type ConnConfig struct {
ConnString string
Pwd string
}
type ConnPool struct {
connPool chan *net.TCPConn
initActive int
}
var pool *ConnPool
var oSingle sync.Once
/**
* 单例的连接池(线程安全)
*/
func NewSingleConnPool(initActive int, config ConnConfig) *ConnPool {
oSingle.Do(func() {
pool, _ = NewConnPool(initActive, config)
})
return pool
}
/**
* 初始化连接池
*/
func NewConnPool(initActive int, config ConnConfig) (*ConnPool, error) {
if initActive <= 0 {
return nil, errors.New("maxActive must gt than 0")
}
var pool ConnPool
channel := make(chan *net.TCPConn, initActive)
pool.initActive = initActive
for index := 0; index < initActive; index++ {
//初始化一个连接
conn := Connect(config.ConnString)
//设置keepalive
conn.SetKeepAlive(true)
//为当前连接授权
auth(conn, config.Pwd)
//将连接加入连接池
channel <- conn
}
pool.connPool = channel
return &pool, nil
}
func auth(conn *net.TCPConn, pwd string){
SendCommand(conn, protocol.AUTH, protocol.SafeEncode(pwd))
}
/**
* 从连接池中获取连接
*/
func GetConn(pool *ConnPool) (*net.TCPConn, error) {
if PoolSize(pool) == 0 {
return nil, errors.New("连接数已不足")
}
conn := <-pool.connPool
if conn == nil {
return nil, errors.New("连接数已不足")
}
return conn, nil
}
/**
* 将连接归还到连接池
*/
func (pool *ConnPool) PutConn(conn *net.TCPConn) error {
if conn == nil {
return errors.New("连接为空")
}
pool.connPool <- conn
return nil
}
/**
* 返回连接池当前连接数
*/
func PoolSize(pool *ConnPool) int {
return len(pool.connPool)
}
项目地址: