golang DB接続プールの作成

5984 ワード

チャネルの使用
import(
    "database/sql"
    _"github.com/go-sql-driver/mysql"
    "log"
    "time"
    "math/rand"
)
//      
var MAX_POOL_SIZE = 20
var dbPoll chan *sql.DB

const (
    user="root"
    pass="root"
    db="school"

)
func putDB(db *sql.DB) {
    //               ,       ,        
    if dbPoll == nil {
        dbPoll = make(chan *sql.DB, MAX_POOL_SIZE)
    }
    if len(dbPoll) >= MAX_POOL_SIZE {
        db.Close()
        return
    }
    dbPoll 

自分で書いた接続プール
db.go
package db

import (
    "time"
    "github.com/Sirupsen/logrus"
    "github.com/jinzhu/gorm"
    _"github.com/go-sql-driver/mysql"
    "reflect"
    "fmt"
    "errors"
    "strconv"
    "youguoju/conf/config"
)

type dB interface {
    Gorm()*gorm.DB
    Id()uint32//ID     
}

type myDB struct {
    db *gorm.DB
    id uint32//ID
}

type DBPoll interface {
    Take()(dB,error)//    
    Return(entity dB)(error)//    
    Total()uint32//     
    Used()uint32//             
}
type myDBPoll struct {
    pool  DBPoll //   
    etype reflect.Type    //       
}
//  DB     
type genDB func() dB
func newDBPoll(total uint32,gen genDB)(DBPoll,error)  {
    etype:=reflect.TypeOf(gen())
    genEntity:= func() dB{return gen()}
    pool,err:= NewPool(total,etype,genEntity)
    if err!=nil {
        return nil,err
    }
    dbpool:=&myDBPoll{pool,etype}
    return dbpool,nil
}

func (db *myDB)Id()uint32  {
    return db.id
}
func (db *myDB)Gorm()*gorm.DB {
    return db.db
}
//    
func (pool *myDBPoll)Take()(dB,error){
    entity,err:=pool.pool.Take()
    if err!=nil {
        return nil,err
    }
    dl,ok:=entity.(dB)//      
    if !ok {
        errMsg:=fmt.Sprintf("The type of entity id NOT %s
",pool.etype) panic(errors.New(errMsg)) } return dl,nil } // func (pool *myDBPoll)Return(entity dB)(error){ return pool.pool.Return(entity) } // func (pool *myDBPoll)Total()uint32{ return pool.pool.Total() } // func (pool *myDBPoll)Used()uint32{ return pool.pool.Used() } var dbPoll DBPoll func InitDB() { total := config.Conf.Total to,_:=strconv.Atoi(total) dbPoll,_=newDBPoll(uint32(to),initDb) } //func GetDBPollInstance() DBPoll { // return dbPoll //} func GetDBInstance() (dB,error) { db,err:=dbPoll.Take() if err!=nil { return nil, err } return db,nil } func ReturnDB(db dB) error { return dbPoll.Return(db) } func initDb() dB{ var db *gorm.DB var err error path := config.Conf.DBURL // env logrus.Info("path:", string(path)) // for { db, err = gorm.Open("mysql", string(path)) // gorm if err != nil { logrus.Error(err, "Retry in 2 seconds!") time.Sleep(time.Second * 2) continue } logrus.Info("DB connect successful!") break } return &myDB{db:db,id:idGenertor.GetUint32()} } var idGenertor IdGenertor = NewIdGenertor()

pool.go
package db


import (
"reflect"
"fmt"
"errors"
"sync"
)

type Pool interface {
    Take()(dB,error)//    
    Return(entity dB)(error)//    
    Total()uint32//     
    Used()uint32//             
}
////       
//type Entity1 interface {
//  Id()uint32//ID     
//}

//        
type myPool struct {
    total uint32//     
    etype reflect.Type//       
    genEntity func()dB//         
    container chan dB//    
    //  Id   
    idContainer map[uint32]bool
    mutex sync.Mutex
}

func NewPool(total uint32,entityType reflect.Type,genEntity func()dB)(Pool,error)  {
    if total==0 {
        errMsg:=fmt.Sprintf("The pool can not be initialized! (total=%d)
",total) return nil,errors.New(errMsg) } size:=int(total) container:=make(chan dB,size) idContainer:=make(map[uint32]bool) for i:=0;i

idジェネレータ
package db

import (
    "sync"
    "math"
)

type IdGenertor interface {
    GetUint32() uint32//    unit32   Id
}
type cyclicIdGenertor struct {
    id uint32//  id
    ended bool//   id              
    mutex sync.Mutex
}

func NewIdGenertor() IdGenertor {
    return &cyclicIdGenertor{}
}
//    unit32   Id
func (gen *cyclicIdGenertor)GetUint32() uint32 {
    gen.mutex.Lock()
    defer gen.mutex.Unlock()
    if gen.ended {
        defer func() {gen.ended=false}()
        gen.id=uint32(1)
        return uint32(0)
    }
    id:=gen.id
    if  id

使用
//  token            
func (user *User)GetUserByTokenFromDB(token string)(bool)  {
    instance,err:=db.GetDBInstance()
    defer db.ReturnDB(instance)
    if err!=nil {
        return false
    }
    gorm:=instance.Gorm()
    gorm.Where("Token = ?", token).Find(&user)
    return true
}