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

zhuhui901222 · · 1584 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

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

1584 次点击  
加入收藏 微博
3 回复  |  直到 2019-04-08 16:54:13
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传