This is a creation in Article, where the information may have evolved or changed.
Some ideas when you just started writing a connection pool:
1, Connection pool is the most important is the idle, busy and peak connection operation logic;
2, connection pooling tools with MySQL, Redis, TCP, no specific relationship, as long as the production mode is IO. Closer interface can be;
3, Connection pool Most of the time after the connection using the release will be rollback, here is the direct close operation (most operations are directly connected back to the pool reuse), but I here consider that the service connection may be affected by the network fluctuations, so simply to close
4, there is a separate coprocessor constantly in the monitoring connection pool of Chan io. Closer continuous connection replenishment, status changes (e.g. idle, busy switching)
Not much nonsense on Pool.go code
Package Coreimport ("Errors" "Time" "Sync" "io" "FMT")//Connection pool production type poolfactory func () (IO. Closer, error)//connection pool management instance type pool struct {mu sync. Mutex maxidle int Maxopen int isdebug bool Name string busy bool factory poolfactory Stack Ch An IO. Closer}//new Mysqlpoolfunc Newpool (Factory poolfactory, Maxidle int, Maxopen int, name string) *pool {pool: = new (Pool ) pool. Name = Name Pool.factory = Factory Pool.setinit (maxidle, Maxopen) return Pool}//logfunc (this *pool) log (value: . interface{}) {if this. Isdebug {fmt. Println ("[Pool]", this. Name, value)}}//set Initfunc (this *pool) setinit (maxidle int, Maxopen int) Error {if Maxopen < Maxidle { return errors. New ("Maxopen can not less than than Maxidle")} This.stack = Make (chan io. Closer, Maxopen) go func () {for {busystate: = this.busy && len (this.stack) < Maxopen Idlestate: = Len (this.stack) < Maxidle If Maxidle <= 0 | | Busystate | | idlestate {One, err: = This.factory () if Err = = Nil {this.stack <-o NE} this.log ("Create One", Len (This.stack))} time. Sleep (time. Microsecond}} () return Nil}//back to Poolfunc (this *pool) back (one IO. Closer) Error {if one! = Nil {return one. Close ()} return errors. New ("Back instance are nil")}//get Instancefunc (this *pool) get () (IO. Closer, error) {This.mu.Lock () defer this.mu.Unlock () if this. Maxidle > 0 && len (this.stack) < this. Maxidle {this.busy = true} else {this.busy = false} Select {Case one: = <-this.stack: This.log ("Use one") return one, nil case <-time. After (time. Microsecond *): This.busy = True return nil, errors. New ("Pool Timeout")}}
How do I use connection pooling? Ash is always simple
Here Gorm is used to create a MySQL connection for facotry pool factory creation
package mainimport ( _ "github.com/go-sql-driver/mysql" "io" "core")var pool *core.Poolfunction main(){ pool = core.NewPool(poolMysqlFactory, 5, 50, "mysql") pool.IsDebug = true //use pool err,conn := pool.Get() //balabala use conn conn.Close() time.Sleep(time.Hour*1)}//mysql pool factoryfunc poolMysqlFactory() (io.Closer, error) { conn, err := gorm.Open("mysql", "username:password@tcp(localhost:3306)/test?charset=utf8&parseTime=True&loc=Local") if err != nil { return nil, err } return conn, nil}