來(lái)源: Clement-Xu 發(fā)布時(shí)間:2018-11-01 10:21:29 閱讀量:1063
而且,網(wǎng)上對(duì)于BoneCP是好評(píng)如潮啊,推薦的文章一搜一大堆。
然而,上Maven Repository網(wǎng)站(http://mvnrepository.com/artifact/com.jolbox/bonecp)查找有沒(méi)有最新版本的時(shí)候,你會(huì)發(fā)現(xiàn)最新的是2013年10月份的(這么久沒(méi)新版本出來(lái)了?)。于是,再去BoneCP的Githut(https://github.com/wwadge/bonecp)上看看最近有沒(méi)有提交代碼。卻發(fā)現(xiàn),BoneCP的作者對(duì)于這個(gè)項(xiàng)目貌似已經(jīng)心灰意冷,說(shuō)是要讓步給HikariCP了(有圖有真相):
……什么?又來(lái)一個(gè)CP?……什么是Hikari?
Hikari來(lái)自日文,是“光”(陽(yáng)光的光,不是光禿禿的光)的意思。作者估計(jì)是為了借助這個(gè)詞來(lái)暗示這個(gè)CP速度飛快。不知作者是不是日本人,不過(guò)日本也有很多優(yōu)秀的碼農(nóng),聽(tīng)說(shuō)比特幣據(jù)說(shuō)日本人搞出來(lái)的。。。
這個(gè)產(chǎn)品的口號(hào)是“快速、簡(jiǎn)單、可靠”。實(shí)際情況跟這個(gè)口號(hào)真的匹配嗎?又是有圖有真相(Benchmarks又來(lái)了):
這個(gè)圖,也間接地、再一次地證明了boneCP比c3p0強(qiáng)大很多,當(dāng)然,跟“光”比起來(lái),又弱了不少啊。
那么,這么好的P是怎么做到的呢?官網(wǎng)詳細(xì)地說(shuō)明了HikariCP所做的一些優(yōu)化,總結(jié)如下:
字節(jié)碼精簡(jiǎn):優(yōu)化代碼,直到編譯后的字節(jié)碼最少,這樣,CPU緩存可以加載更多的程序代碼;
優(yōu)化代理和攔截器:減少代碼,例如HikariCP的Statement proxy只有100行代碼,只有BoneCP的十分之一;
自定義數(shù)組類(lèi)型(FastStatementList)代替ArrayList:避免每次get()調(diào)用都要進(jìn)行range check,避免調(diào)用remove()時(shí)的從頭到尾的掃描;
自定義集合類(lèi)型(ConcurrentBag):提高并發(fā)讀寫(xiě)的效率;
其他針對(duì)BoneCP缺陷的優(yōu)化,比如對(duì)于耗時(shí)超過(guò)一個(gè)CPU時(shí)間片的方法調(diào)用的研究(但沒(méi)說(shuō)具體怎么優(yōu)化)。
很多優(yōu)化的對(duì)比都是針對(duì)BoneCP的……哈哈。
(參考文章:https://github.com/brettwooldridge/HikariCP/wiki/Down-the-Rabbit-Hole)
幾個(gè)連接池的代碼量對(duì)比(代碼量越少,一般意味著執(zhí)行效率越高、發(fā)生bug的可能性越低):
可是,“黃婆賣(mài)瓜,自催自擂”這個(gè)俗語(yǔ)日本人也是懂得,于是,用戶(hù)的好評(píng)如潮也是有圖有真相:
還有第三方關(guān)于速度的測(cè)試:
也許你會(huì)說(shuō),速度高,如果不穩(wěn)定也是硬傷啊。于是,關(guān)于穩(wěn)定性的圖也來(lái)了:
另外,關(guān)于可靠性方面,也是有實(shí)驗(yàn)和數(shù)據(jù)支持的。對(duì)于數(shù)據(jù)庫(kù)連接中斷的情況,通過(guò)測(cè)試getConnection(),各種CP的不相同處理方法如下:
(所有CP都配置了跟connectionTimeout類(lèi)似的參數(shù)為5秒鐘)
HikariCP:等待5秒鐘后,如果連接還是沒(méi)有恢復(fù),則拋出一個(gè)SQLExceptions 異常;后續(xù)的getConnection()也是一樣處理;
C3P0:完全沒(méi)有反應(yīng),沒(méi)有提示,也不會(huì)在“CheckoutTimeout”配置的時(shí)長(zhǎng)超時(shí)后有任何通知給調(diào)用者;然后等待2分鐘后終于醒來(lái)了,返回一個(gè)error;
Tomcat:返回一個(gè)connection,然后……調(diào)用者如果利用這個(gè)無(wú)效的connection執(zhí)行SQL語(yǔ)句……結(jié)果可想而知;大約55秒之后終于醒來(lái)了,這時(shí)候的getConnection()終于可以返回一個(gè)error,但沒(méi)有等待參數(shù)配置的5秒鐘,而是立即返回error;
BoneCP:跟Tomcat的處理方法一樣;也是大約55秒之后才醒來(lái),有了正常的反應(yīng),并且終于會(huì)等待5秒鐘之后返回error了;
可見(jiàn),HikariCP的處理方式是最合理的。根據(jù)這個(gè)測(cè)試結(jié)果,對(duì)于各個(gè)CP處理數(shù)據(jù)庫(kù)中斷的情況,評(píng)分如下:
參考文章:https://github.com/brettwooldridge/HikariCP/wiki/Bad-Behavior:-Handling-Database-Down
說(shuō)得這么好,用起來(lái)會(huì)不會(huì)很麻煩啊,會(huì)不會(huì)有很多參數(shù)要配置才能有這樣的效果???答案是:不會(huì)。
如果之前用的是BoneCP配置的數(shù)據(jù)源,那么,就簡(jiǎn)單了,只需要把dataSource換一下,稍微調(diào)整一下參數(shù)就行了:
BoneCP的數(shù)據(jù)源配置:
<!-- BoneCp Datasource -->
<bean id="dataSourceBoneCp" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${db.driverClass}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="idleConnectionTestPeriodInMinutes" value="2" />
<property name="idleMaxAgeInMinutes" value="2" />
<property name="maxConnectionsPerPartition" value="2" />
<property name="minConnectionsPerPartition" value="0" />
<property name="partitionCount" value="2" />
<property name="acquireIncrement" value="1" />
<property name="statementsCacheSize" value="100" />
<property name="lazyInit" value="true"/>
<property name="maxConnectionAgeInSeconds" value="20"/>
<property name="defaultReadOnly" value="true"/>
</bean>
HiKariCP的數(shù)據(jù)源配置:
<!-- Hikari Datasource -->
<bean id="dataSourceHikari" class="com.zaxxer.hikari.HikariDataSource" destroy-method="shutdown">
<!-- <property name="driverClassName" value="${db.driverClass}" /> --> <!-- 無(wú)需指定,除非系統(tǒng)無(wú)法自動(dòng)識(shí)別 -->
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<!-- 連接只讀數(shù)據(jù)庫(kù)時(shí)配置為true, 保證安全 -->
<property name="readOnly" value="false" />
<!-- 等待連接池分配連接的最大時(shí)長(zhǎng)(毫秒),超過(guò)這個(gè)時(shí)長(zhǎng)還沒(méi)可用的連接則發(fā)生SQLException, 缺省:30秒 -->
<property name="connectionTimeout" value="30000" />
<!-- 一個(gè)連接idle狀態(tài)的最大時(shí)長(zhǎng)(毫秒),超時(shí)則被釋放(retired),缺省:10分鐘 -->
<property name="idleTimeout" value="600000" />
<!-- 一個(gè)連接的生命時(shí)長(zhǎng)(毫秒),超時(shí)而且沒(méi)被使用則被釋放(retired),缺省:30分鐘,建議設(shè)置比數(shù)據(jù)庫(kù)超時(shí)時(shí)長(zhǎng)少30秒,參考MySQL wait_timeout參數(shù)(show variables like '%timeout%';) -->
<property name="maxLifetime" value="1800000" />
<!-- 連接池中允許的最大連接數(shù)。缺省值:10;推薦的公式:((core_count * 2) + effective_spindle_count) -->
<property name="maximumPoolSize" value="15" />
</bean>
其中,很多配置都使用缺省值就行了,除了maxLifetime和maximumPoolSize要注意自己計(jì)算一下。
其他的配置(sqlSessionFactory、MyBatis MapperScannerConfigurer、transactionManager等)統(tǒng)統(tǒng)不用變。
其他關(guān)于Datasource配置參數(shù)的建議:
Configure your HikariCP idleTimeout and maxLifeTime settings to be one minute less than the wait_timeout of MySQL.
對(duì)于有Java連接池的系統(tǒng),建議MySQL的wait_timeout使用缺省的8小時(shí)(http://www.rackspace.com/knowledge_center/article/how-to-change-the-mysql-timeout-on-a-server)。
---------------------
作者:Clement-Xu
來(lái)源:CSDN
原文:https://blog.csdn.net/ClementAD/article/details/46928621
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
在線
客服
服務(wù)時(shí)間:周一至周日 08:30-18:00
選擇下列產(chǎn)品馬上在線溝通:
客服
熱線
7*24小時(shí)客服服務(wù)熱線
關(guān)注
微信
關(guān)注官方微信