最近在弄beego,分享一个整理的mysql连接池

zhuhui901222 · 2019-04-08 15:28:14 · 1746 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2019-04-08 15:28:14 的主题,其中的信息可能已经有所发展或是发生改变。

package main

import ( "errors" "fmt" "github.com/gohouse/gorose" "sync" "time" )

//频繁的创建和关闭连接,对系统会造成很大负担 //所以我们需要一个池子,里面事先创建好固定数量的连接资源,需要时就取,不需要就放回池中。 //但是连接资源有一个特点,我们无法保证连接长时间会有效。 //比如,网络原因,人为原因等都会导致连接失效。 //所以我们设置一个超时时间,如果连接时间与当前时间相差超过超时时间,那么就关闭连接。

type Factory struct { conn *gorose.Connection err error }

func (factory *Factory)Close(){ factory.conn.Close() }

func (factory Factory)factory()(conn gorose.Connection,err error){ return factory.conn,factory.err }

//工厂方法,用于创建连接资源

func NewConn()(factory Factory){ var dbConfig = &gorose.DbConfigSingle{ Driver: "mysql", // driver: mysql/sqlite/oracle/mssql/postgres EnableQueryLog: true, // if enable sql logs SetMaxOpenConns: 0, // connection pool of max Open connections, default zero SetMaxIdleConns: 0, // connection pool of max sleep connections Prefix: "", // prefix of table Dsn: "root:root@tcp(localhost:3306)/test?charset=utf8", // db dsn } // 初始化数据库链接, 默认会链接配置中 default 指定的值 // 也可以在第二个参数中指定对应的数据库链接, 见下边注释的那一行链接示例 connection, err :=gorose.Open(dbConfig ) return Factory{connection,err} }

//连接 type Conn struct { conn *gorose.Connection //连接时间 time time.Time }

//连接池 type ConnPool struct { //互斥锁,保证资源安全 mu sync.Mutex //通道,保存所有连接资源 conns chan *Conn //工厂方法,创建连接资源 factory Factory //判断池是否关闭 closed bool //连接超时时间 connTimeOut time.Duration }

//创建一个连接资源池 func NewConnPool(factory Factory, cap int, connTimeOut time.Duration) (*ConnPool, error) { if cap <= 0 { return nil, errors.New("cap不能小于0") } if connTimeOut <= 0 { return nil, errors.New("connTimeOut不能小于0") }

cp := &ConnPool{
    mu:          sync.Mutex{},
    conns:       make(chan *Conn, cap),
    factory:     factory,
    closed:      false,
    connTimeOut: connTimeOut,
}
for i := 0; i < cap; i++ {
    //通过工厂方法创建连接资源
    newConn:=NewConn()
    conn1, err := newConn.factory()
    if err != nil {
        cp.Close()
        return nil, errors.New("factory出错")
    }
    //将连接资源插入通道中
    cp.conns <- &Conn{conn: conn1, time: time.Now()}
}
return cp, nil

}

//获取连接资源 func (cp ConnPool) Get() (gorose.Connection, error) { if cp.closed { return nil, errors.New("连接池已关闭") }

for {
    select {
    //从通道中获取连接资源
    case connRes, ok := <-cp.conns:
        {
            if !ok {
                return nil, errors.New("连接池已关闭")
            }
            //判断连接中的时间,如果超时,则关闭
            //继续获取
            if time.Now().Sub(connRes.time) > cp.connTimeOut {
                connRes.conn.Close()
                continue
            }
            return connRes.conn, nil
        }
    default:
        {
            //如果无法从通道中获取资源,则重新创建一个资源返回
            newConn:=NewConn()
            connRes, err := newConn.factory()
            if err != nil {
                return nil, err
            }
            return connRes, nil
        }
    }
}

}

//连接资源放回池中 func (cp ConnPool) Put(conn gorose.Connection) error { if cp.closed { return errors.New("连接池已关闭") }

select {
//向通道中加入连接资源
case cp.conns <- &Conn{conn: conn, time: time.Now()}:
    {
        return nil
    }
default:
    {
        //如果无法加入,则关闭连接
        conn.Close()
        return errors.New("连接池已满")
    }
}

}

//关闭连接池 func (cp *ConnPool) Close() { if cp.closed { return } cp.mu.Lock() cp.closed = true //关闭通道 close(cp.conns) //循环关闭通道中的连接 for conn := range cp.conns { conn.conn.Close() } cp.mu.Unlock() }

//返回池中通道的长度 func (cp *ConnPool) len() int { return len(cp.conns) }

func main() {

cp, _ := NewConnPool(NewConn(), 10, time.Second*10)

//获取资源
conn1, _ := cp.Get()
conn2, _ := cp.Get()

//这里连接池中资源大小为8
fmt.Println("cp len : ", cp.len())
//var session  *gorose.Connection
session:= conn1.NewSession()

res,err := session.Table("users").First()
if err!=nil{
    fmt.Println("db.Table",err)
    return
}
fmt.Println(res)

//把2个连接资源放回池中
cp.Put(conn1)
cp.Put(conn2)
//这里显示为3
fmt.Println("cp len : ", cp.len())
cp.Close()

}


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1746 次点击  
加入收藏 微博
3 回复  |  直到 2019-04-08 16:54:13
sam6666666
sam6666666 · #1 · 6年之前

http和sql都自带连接池

jarlyyn
jarlyyn · #2 · 6年之前

sql库自带连接池吧……

sam6666666
sam6666666 · #3 · 6年之前
jarlyynjarlyyn #2 回复

sql库自带连接池吧……

http和sql都自带连接池

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传