思路
为了复用tcp连接,减少建立新连接的开销,实现连接池思路如下:
1, 初始化连接池的容量大小
2, 客户端从连接池中获取连接,若无可用连接则创建新连接并放入连接池,若有则从连接池中取出
3,使用完连接后,将连接重新放回连接池中
4, 定期检查连接池连接是否可用,不可用则剔除连接池
代码
package main
import (
"errors"
"fmt"
"net"
)
type ConnPool struct {
address string
channel chan net.Conn
capacity int
}
func NewConnPool(address string, capacity int) *ConnPool {
return &ConnPool{
address: address,
channel: make(chan net.Conn, capacity), // 初始化连接池
capacity: capacity,
}
}
func (p *ConnPool) GetConn() (net.Conn, error) {
select {
case conn := <-p.channel: // 有连接直接返回
return conn, nil
default: // 无连接则创建并塞入连接池
if len(p.channel) < p.capacity {
conn, err := net.Dial("tcp", p.address)
if err != nil {
return nil, err
}
p.channel <- conn
return conn, nil
}
return nil, errors.New("connection pool overflow")
}
}
func (p *ConnPool) PutConn(conn net.Conn) {
select {
case p.channel <- conn: // 释放连接后重新放回连接池
default:
conn.Close() // 连接池已满则直接关闭
}
}
func main() {
pool := NewConnPool("127.0.0.1:3306", 64)
conn, err := pool.GetConn()
if err != nil {
fmt.Println(err)
return
}
defer pool.PutConn(conn)
// transfer data ...
}