golang DB接続プールの作成
5984 ワード
チャネルの使用
自分で書いた接続プール
db.go
pool.go
idジェネレータ
使用
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
}