1、建立連線和關閉連線 2、池子裡面取conn的管理 3、監控統計 4、整個pooler池子的關閉
結構體
type connpool struct
//池子裡面空閒的conn的同步channel
connsmu sync.mutex
conns [
]*conn //活躍的active conns
idleconnsmu sync.rwmutex
idleconns [
]*conn //空閒的idle conns
stats stats
_closed uint32
// atomic //池子是否關閉標籤
}
初始化連線池var
_ pooler =
(*connpool)
(nil
)//介面檢查
func
newconnpool
(opt *options)
*connpool
, opt.poolsize)
,//同步用的
conns:
make([
]*conn,
0, opt.poolsize)
, idleconns:
make([
]*conn,
0, opt.poolsize),}
if opt.idletimeout >
0&& opt.idlecheckfrequency >
0return p
}//reaper字面意思為收割者,為清理的意思
func
(p *connpool)
reaper
(frequency time.duration)
//定時清理無用的conns
n, err := p.
reapstaleconns()
if err !=
nil atomic.
adduint32
(&p.stats.staleconns,
uint32
(n))}}
func
(p *connpool)
reapstaleconns()
(int
,error
)//處理完了,釋放占用的channel的位置
p.freeturn()
if cn !=
nilelse
}return n,
nil}
func
(p *connpool)
reapstaleconn()
*conn
//取第乙個空閒conn
cn := p.idleconns[0]
//判斷是否超時沒有人用
if!cn.
isstale
(p.opt.idletimeout)
//超時沒有人用則從空閒列表裡面移除
p.idleconns =
(p.idleconns[:0
], p.idleconns[1:
]...
)return cn
}//判斷是否超時的處理
func
(cn *conn)
isstale
(timeout time.duration)
bool
//移除連線就是乙個很簡單的遍歷
func
(p *connpool)
removeconn
(cn *conn)
} p.connsmu.
unlock()
}
建立連線func
(p *connpool)
newconn()
(*conn,
error)
p.connsmu.
lock()
//建立好後加入conns中
p.conns =
(p.conns, cn)
p.connsmu.
unlock()
return cn,
nil}
func
(p *connpool)
newconn()
(*conn,
error
)//判斷是否一直出錯
if atomic.
loaduint32
(&p.dialerrorsnum)
>=
uint32
(p.opt.poolsize)
netconn, err := p.opt.
dialer()
if err !=
nilreturn
nil, err
}return
newconn
(netconn)
,nil
}func
(p *connpool)
trydial()
//就是不斷的dailer直到成功
conn, err := p.opt.
dialer()
if err !=
nil//dialer成功,則設定dialerrorsnum為0
atomic.
storeuint32
(&p.dialerrorsnum,0)
_= conn.
close()
return
}}
從乙個連線池中獲取乙個連線(get)func
(p *connpool)
get()(
*conn,
error
)//等待有空閒,通過channel方式同步,如果池子裡面滿了,則會阻塞等待,但是不會一直阻塞,有乙個超時機制
err := p.
waitturn()
if err !=
nilfor
//取出空閒的,並判斷conn是否過期
if cn.
isstale
(p.opt.idletimeout)
atomic.
adduint32
(&p.stats.hits,1)
return cn,
nil}
//沒有取到conn,miss了
atomic.
adduint32
(&p.stats.misses,1)
//建立新的連線
newcn, err := p.
newconn()
if err !=
nilreturn newcn,
nil}
是get方法成功的時候就往channel裡面寫,put方法成功就往channel裡面讀,釋放出來位置
func
(p *connpool)
waitturn()
error
:return
nildefault
: timer := timers.
get().
(*time.timer)
timer.
reset
(p.opt.pooltimeout)
select:if
!timer.
stop()
timers.
put(timer)
return
nilcase
<-timer.c:
//超時寫入機制
timers.
put(timer)
atomic.
adduint32
(&p.stats.timeouts,1)
return errpooltimeout
}}}
putfunc
(p *connpool)
put(cn *conn)
p.idleconnsmu.
lock()
//放入空閒conns裡面來,方便get的時候取出來
p.idleconns =
(p.idleconns, cn)
p.idleconnsmu.
unlock()
//get成功時候是寫入channel,這個時候自然是釋放channel
p.freeturn()
}
資料庫連線池Hikaricp原始碼分析
hikaricp總結 借助哪些技術使效能超越其他執行緒池的?為了效能,自定義資料結構 fastlist concurrentbag 主要就是concurrentbag使用threadlocal sharelist 等待queue 對獲取connnection做了優化。定時器相關的使用 schedul...
Mybatis自帶連線池原始碼解析
poolmaximumactiveconnections 連線池最大活躍連線數,預設為10個。poolmaximumidleconnections 連線池最大空閒連線數,預設為5個。poolmaximumcheckouttime 最大可 時間,當活躍連線數達到上限時,如果此時有連線請求,則會檢查當前...
深入分析連線池技術 模擬實現連線池
模擬實現資料庫連線池連線池類 connectionpool 模擬資料庫連線池的操作流程 1.建立乙個資料庫連線池 2.初始10個連線物件 3.來乙個客戶端,從連線池裡取 4.當客戶用完了,則不是真的銷毀,而是放入到連線池中public class connectpool public connect...