boneCP是一款關(guān)注高性能的數(shù)據(jù)庫(kù)連接池產(chǎn)品 github主頁(yè) 。

不過(guò)最近作者好像沒(méi)有心思更新了,因?yàn)樗l(fā)現(xiàn)了一款更快的連接池產(chǎn)品,但是這不影響我學(xué)習(xí)它。

連接的生存時(shí)間

MySQL有一個(gè)重要的參數(shù)wait_timeout,用于規(guī)定一個(gè)connection最大的idle時(shí)間,默認(rèn)是28800秒,即每個(gè)connection連續(xù)的sleep狀態(tài)不能超過(guò)該值,否則MySQL會(huì)自動(dòng)回收該connection。

連接池的作用是管理連接,任何想要請(qǐng)求數(shù)據(jù)庫(kù)連接的行為都和連接池發(fā)生交互,從連接池里申請(qǐng)連接,使用完成后將連接交還給連接池。

在一個(gè)比較空閑的系統(tǒng)上,連接可能長(zhǎng)時(shí)間的處于sleep狀態(tài),那么一旦達(dá)到了MySQL wait_timeout的規(guī)定時(shí)間,MySQL就要回收連接,這時(shí)連接池如果仍然認(rèn)為該connection可用,待應(yīng)用向連接池請(qǐng)求時(shí),就會(huì)將不存在的connection資源交給應(yīng)用,這樣就會(huì)報(bào)錯(cuò)。

因此連接池需要一套機(jī)制保證每一個(gè)connection在連接池生存期內(nèi)是始終可用的。

我推測(cè)應(yīng)該有兩種機(jī)制:定期檢測(cè)和申請(qǐng)時(shí)檢測(cè)。

boneCP采用定期檢測(cè)機(jī)制,即每隔一個(gè)時(shí)間間隔就會(huì)檢查其管理的連接處于sleep狀態(tài)的時(shí)間,如果超過(guò)了設(shè)定的值,則會(huì)將此connection重建。

boneCP中有兩個(gè)很重要的參數(shù):idleConnectionTestPeriodInSeconds和idleMaxAgeInSeconds,分別是連接探測(cè)時(shí)間閾值和連接最大空閑時(shí)間,默認(rèn)值為4小時(shí)和1小時(shí)。

boneCP會(huì)啟動(dòng)三個(gè)線程來(lái)進(jìn)行定期任務(wù):

this.keepAliveScheduler =  Executors.newScheduledThreadPool(this.config.getPartitionCount(), new CustomThreadFactory("BoneCP-keep-alive-scheduler"+suffix, true));this.maxAliveScheduler =  Executors.newScheduledThreadPool(this.config.getPartitionCount(), new CustomThreadFactory("BoneCP-max-alive-scheduler"+suffix, true));this.connectionsScheduler =  Executors.newFixedThreadPool(this.config.getPartitionCount(), new CustomThreadFactory("BoneCP-pool-watch-thread"+suffix, true));

其中keepAliveScheduler用來(lái)每隔一段時(shí)間檢查connection的sleep狀態(tài)時(shí)間是否達(dá)到了idleMaxAgeInSeconds或者是否已經(jīng)失效,如果是,則會(huì)將連接kill掉,主要的邏輯見(jiàn)ConnectionTesterThread.java。

需要注意的是,在默認(rèn)的配置下,該檢查的調(diào)度是這樣定義的:

this.keepAliveScheduler.scheduleAtFixedRate(connectionTester,delayInSeconds,&