前言
golang的channel除了goroutine通信之外還有很多其他的功能,本文將實(shí)現(xiàn)一種基于channel的通用連接池。下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
功能
* 連接池中連接類型為interface{},使得更加通用
* 鏈接的最大空閑時(shí)間,超時(shí)的鏈接將關(guān)閉丟棄,可避免空閑時(shí)鏈接自動(dòng)失效問(wèn)題
* 使用channel處理池中的鏈接,高效
何為通用?
連接池的實(shí)現(xiàn)不依賴具體的實(shí)例,而依賴某個(gè)接口,本文的連接池選用的是io.Closer接口,只要是實(shí)現(xiàn)了該接口的對(duì)象都可以被池管理。
當(dāng)然,你可以實(shí)現(xiàn)基于interface{}的連接池,這樣任何對(duì)象都可以被管理。
實(shí)現(xiàn)原理
將連接句柄存入channel中,由于緩存channel的特性,獲取連接時(shí)如果池中有連接,將直接返回,如果池中沒(méi)有連接,將阻塞或者新建連接(沒(méi)超過(guò)最大限制的情況下)。
由于面向接口編程,所有創(chuàng)建連接的邏輯是不清楚的,這里需要傳入一個(gè)函數(shù),該函數(shù)返回一個(gè)io.Closer對(duì)象。
實(shí)現(xiàn)
由于并發(fā)問(wèn)題,在需要操作池中互斥數(shù)據(jù)的時(shí)候需要加鎖。
package pool import ( "errors" "io" "sync" "time" ) var ( ErrInvalidConfig = errors.New("invalid pool config") ErrPoolClosed = errors.New("pool closed") ) type factory func() (io.Closer, error) type Pool interface { Acquire() (io.Closer, error) // 獲取資源 Release(io.Closer) error // 釋放資源 Close(io.Closer) error // 關(guān)閉資源 Shutdown() error // 關(guān)閉池 } type GenericPool struct { sync.Mutex pool chan io.Closer maxOpen int // 池中最大資源數(shù) numOpen int // 當(dāng)前池中資源數(shù) minOpen int // 池中最少資源數(shù) closed bool // 池是否已關(guān)閉 maxLifetime time.Duration factory factory // 創(chuàng)建連接的方法 } func NewGenericPool(minOpen, maxOpen int, maxLifetime time.Duration, factory factory) (*GenericPool, error) { if maxOpen = 0 || minOpen > maxOpen { return nil, ErrInvalidConfig } p := GenericPool{ maxOpen: maxOpen, minOpen: minOpen, maxLifetime: maxLifetime, factory: factory, pool: make(chan io.Closer, maxOpen), } for i := 0; i minOpen; i++ { closer, err := factory() if err != nil { continue } p.numOpen++ p.pool - closer } return p, nil } func (p *GenericPool) Acquire() (io.Closer, error) { if p.closed { return nil, ErrPoolClosed } for { closer, err := p.getOrCreate() if err != nil { return nil, err } // todo maxLifttime處理 return closer, nil } } func (p *GenericPool) getOrCreate() (io.Closer, error) { select { case closer := -p.pool: return closer, nil default: } p.Lock() if p.numOpen >= p.maxOpen { closer := -p.pool p.Unlock() return closer, nil } // 新建連接 closer, err := p.factory() if err != nil { p.Unlock() return nil, err } p.numOpen++ p.Unlock() return closer, nil } // 釋放單個(gè)資源到連接池 func (p *GenericPool) Release(closer io.Closer) error { if p.closed { return ErrPoolClosed } p.Lock() p.pool - closer p.Unlock() return nil } // 關(guān)閉單個(gè)資源 func (p *GenericPool) Close(closer io.Closer) error { p.Lock() closer.Close() p.numOpen-- p.Unlock() return nil } // 關(guān)閉連接池,釋放所有資源 func (p *GenericPool) Shutdown() error { if p.closed { return ErrPoolClosed } p.Lock() close(p.pool) for closer := range p.pool { closer.Close() p.numOpen-- } p.closed = true p.Unlock() return nil }
結(jié)論
基于該連接池,可以管理所有io.Closer對(duì)象。比如memcached,redis等等,非常方便!
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
標(biāo)簽:東營(yíng) 瀘州 阿壩 晉中 昭通 泰安 駐馬店 滄州
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《golang實(shí)現(xiàn)基于channel的通用連接池詳解》,本文關(guān)鍵詞 golang,實(shí)現(xiàn),基于,channel,的,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。