池(Pool)技術在一定程度上可以明顯最佳化伺服器應用程式的效能,提高程式執行效率和降低系統資源開銷。這裡所說的池是一種廣義上的池,比如資料庫連接池、線程池、記憶體池、對象池等。其中,對象池可以看成儲存對象的容器,在進程初始化時建立一定數量的對象。需要時直接從池中取出一個空閑對象,用完後並不直接釋放掉對象,而是再放到對象池中以方便下一次對象請求可以直接複用。其他幾種池的設計思想也是如此,池技術的優勢是,可以消除對象建立所帶來的延遲,從而提高系統的效能。
要瞭解Java串連池我們先要瞭解資料庫連接池(connection pool)的原理,Java串連池正是資料庫連接池在Java上的應用。——我們知道,對於共用資源,有一個很著名的設計模式:資源集區(Resource Pool)。
該模式正是為瞭解決資源的頻繁分配﹑釋放所造成的問題。為解決上述問題,可以採用資料庫連接池技術。資料庫連接池的基本思想就是為資料庫連接建立一個“緩衝池”。預先在緩衝池中放入一定數量的串連,當需要建立資料庫連接時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定串連池最大串連數來防止系統無盡的與資料庫連接。更為重要的是我們可以通過串連池的管理機制監視資料庫的串連的數量﹑使用方式,為系統開發﹑測試及效能調整提供依據。
C3P0是一個開放原始碼的JDBC串連池,它在lib目錄中與Hibernate一起發布,包括了實現jdbc3和jdbc2擴充規範說明的Connection 和Statement 池的DataSources 對象。(首頁:http://sourceforge.net/projects/c3p0/)
BoneCP 是一個開源的快速的 JDBC 串連池。BoneCP很小,只有四十幾K(運行時需要log4j和Google Collections的支援,這二者加起來就不小了),而相比之下 C3P0 要六百多K。另外個人覺得 BoneCP 有個缺點是,JDBC驅動的載入是在串連池之外的,這樣在一些應用伺服器的配置上就不夠靈活。當然,體積小並不是 BoneCP 優秀的原因,BoneCP 到底有什麼突出的地方呢,請看看效能測試報告。(首頁:http://jolbox.com/)
DBCP (Database Connection Pool)是一個依賴Jakarta commons-pool對象池機制的資料庫連接池,Tomcat的資料來源使用的就是DBCP。目前 DBCP 有兩個版本分別是 1.3 和 1.4。1.3 版本對應的是 JDK 1.4-1.5 和 JDBC 3,而1.4 版本對應 JDK 1.6 和 JDBC 4。因此在選擇版本的時候要看看你用的是什麼 JDK 版本了,功能上倒是沒有什麼區別。(首頁:http://commons.apache.org/dbcp/)
Proxool是一個Java SQL Driver驅動程式,提供了對你選擇的其它類型的驅動程式的串連池封裝。可以非常簡單的移植到現存的代碼中。完全可配置。快速,成熟,健壯。可以透明地為你現存的JDBC驅動程式增加串連池功能。
資料庫連接是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連接的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連接池正是針對這個問題提出來的。資料庫連接池負責分配、管理和釋放資料庫連接,它允許應用程式重複使用一個現有的資料庫連接,而再不是重建立立一個;釋放空閑時間超過最大空閑時間的資料庫連接來避免因為沒有釋放資料庫連接而引起的資料庫連接遺漏。這項技術能明顯提高對資料庫操作的效能。
Java中常用的資料庫連接池有:DBCP 、C3P0、BoneCP、Proxool、DDConnectionBroker、DBPool、XAPool、Primrose、SmartPool、MiniConnectionPoolManager及Druid等。
Java開來源資料串連池: http://www.open-open.com/20.htm
Hibernate常用三種串連池的配置:http://tieba.baidu.com/f?kz=70604644
幾種常用java串連池:http://hi.baidu.com/tangyudee/blog/item/f8bdb43decca892571cf6ced.html
感覺在介紹之前有必要闡述一下串連池的幾個概念,有助於後邊一些文字的理解。
最原始的資料庫使用就是開啟一個串連並進行使用,使用過後一定要關閉串連釋放資源。由於頻繁的開啟和關閉串連對jvm包括資料庫
都有一定的資源負荷,尤其應用壓力較大時資源佔用比較多容易產生效能問題。由此使用串連池的作用就顯現出來,他的原理其實不複雜:
先開啟一定數量的資料庫連接,當使用的時候分配給調用者,調用完畢後返回給串連池,注意返回給串連池後這些串連並不會關閉,而是
準備給下一個調用者進行分配。由此可以看出串連池節省了大量的資料庫連接開啟和關閉的動作,對系統效能提升的益處不言而喻。
幾個概念:
最小串連--應用啟動後隨即開啟的串連數以及後續最小維持的串連數。
最大串連數--應用能夠使用的最多的串連數
串連增長數--應用每次新開啟的串連個數
舉個例子說明串連池的運作:
假設設定了最小和最大的串連為10,20,那麼應用一旦啟動則首先開啟10個資料庫連接,但注意此時資料庫連接池的正在使用數字為0--因為你並沒有使用這些串連,而閒置數量則是10。然後你開始登入,假設登入代碼使用了一個串連進行查詢,那麼此時資料庫連接池的正在使用數字為1、空閑數為9,這並不需要從資料庫開啟串連--因為串連池已經準備好了10個給你留著呢。登入結束了,當前串連池的串連數量是多少?當然是0,因為那個串連隨著事務的結束已經返還給串連池了。然後同時有11個人在同一秒進行登入,會發生什麼:串連池從資料庫新申請(開啟)了一個串連,連同另外的10個一併送出,這個瞬間串連池的使用數是11個,不過沒關係正常情況下過一會兒又會變成0。如果同時有21個人登入呢?那第21個人就只能等前面的某個人登入完畢後釋放串連給他。這時串連池開啟了20個資料庫連接--雖然很可能正在使用數量的已經降為0,那麼20個串連會一直保持嗎?當然不,串連池會在一定時間內關閉一定量的串連還給資料庫,在這個例子裡數字是20-10=10,因為只需要保持最小串連數就好了,而這個時間周期也是串連池裡配置的。
好了,基本概念說完了,言歸正傳進行比較了。
首先說明的一點,為了應用便於移植以及可配置的角度,建議還是使用jndi統一進行串連池的配置。怎麼配置其實網上都有很多例子,
這裡簡單舉個例子(使用spring架構):
首先在應用的上下文定義中配置jndi名稱,如一個resource.xml檔案,裡邊的寫法
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>jdbc/myapp</value></property>
</bean>
注意dataSource這個bean在dao層(hibernate或jdbc)的設定檔裡需要作為dataSource名稱的屬性配置到所有bean中
其中“jdbc/myds”這個就是jndi名稱了,下一步就是在應用伺服器串連池裡進行資料庫連接以及對應的jndi配置了
一 開來源資料串連池
1 dbcp
dbcp可能是使用最多的開源串連池,原因大概是因為配置方便,而且很多開源和tomcat應用例子都是使用的這個串連池吧。
這個串連池可以設定最大和最小串連,串連等待時間等,準系統都有。這個串連池的配置參見附件壓縮包中的:dbcp.xml
使用評價:在具體項目應用中,發現此串連池的持續啟動並執行穩定性還是可以,不過速度稍慢,在大並發量的壓力下穩定性
有所下降,此外不提供串連池監控
2 c3p0
c3p0是另外一個開源的串連池,在業界也是比較有名的,這個串連池可以設定最大和最小串連,串連等待時間等,準系統都有。
這個串連池的配置參見附件壓縮包中的:c3p0.xml。
使用評價:在具體項目應用中,發現此串連池的持續啟動並執行穩定性相當不錯,在大並發量的壓力下穩定性也有一定保證,
此外不提供串連池監控。
3 proxool
proxool這個串連池可能用到的人比較少,但也有一定知名度,這個串連池可以設定最大和最小串連,串連等待時間等,準系統都有。
這個串連池的配置參見附件壓縮包中的:proxool.xml。
使用評價:在具體項目應用中,發現此串連池的持續啟動並執行穩定性有一定問題,有一個需要長時間跑批的任務情境任務,同樣的代碼
在另外2個開源串連池中成功結束,但在proxool中出現異常退出。
但是proxool有一個優勢--串連池監控,這是個很誘人的東西,大概的配置方式就是在web.xml中添加如下定義:
<servlet>
<servlet-name>admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
並在應用啟動後訪問:http://localhost:8080/myapp/admin這個url即可監控
不過proxool本身的包在監測使用中會有編碼問題,附件中有一個
解決此問題的包,參見附件壓縮包中的:proxool-0.9.0RC3.jar。另外需要jdk1.5以上的環境。
總結時刻:
綜上所述,這幾種開源串連池各有優劣,推薦使用c3p0,經檢驗這種串連池效能穩定,承壓能力強。而proxool儘管有明顯的效能問題,
但由於它具備監控功能,因此建議在開發測試時使用,有助於確定是否有串連沒有被關掉,可以排除一些代碼的效能問題。
二 商業中介軟體串連池
上面列舉了幾種開源的串連池,其實可以肯定的說,如果條件允許使用weblogic和websphere等中介軟體,那麼不要猶豫,一定要
使用這些商業層級的中介軟體所內建的資料庫連接池,他們的效能以及調配和開源的不在一個量級,舉個例子,曾經有一個項目,資料量比較大,同樣的代碼應用,在3種開源的串連池裡都多少出現過系統異常,而weblogic和websphere的串連池則正常運行,當然後來發現代碼有一定瑕疵,但也側面說明了商業串連池的強大。
1 weblogic的串連池
weblogic 8 是一個讓人使用起來很輕鬆方便的應用伺服器軟體,但是到了9簡直就是折磨,不知道是bea是怎麼想的,oracle收購了bea以後出了10,比9強不少,但是最喜歡的還是8。。。
題外話不說了,就以8.1版本介紹一下他的資料庫連接池(其實10的配置也差不多)
首先是串連池的基本設定,這個不講了,網上有很多教程。然後進入Data Sources菜單配置資料來源裡邊的JNDI Name,要和之前在應用配置中的一致:jdbc/myapp。
然後是串連池一些具體項目的配置,包括設定最小(Initial Capacity),最大( Maximum Capacity)串連,以及
每次串連增加時需要一次性增加多少串連(Capacity Increment)。Allow Shrinking(是否把不用的串連退還資料庫以保持最小串連數--這個就可以參見之前的串連池闡述的例子進行理解了)。
另外還有幾個有意思的選項Test Reserved Connections:對取得的串連進行測試,Test Released Connections:對釋放的串連進行測試。有人會問了,這個有什麼用啊?
不知道大家在項目中有沒有遇到java報串連失效的異常,反正我碰到過,只有在系統壓力大的時候才出現。而有了這個選項就不用擔心這個問題了--因為串連池已經幫你測試了,一旦檢查到串連是無效的他會廢棄掉還給資料庫,只給你有效。不過這個串連失效的異常其實多半是應用的不嚴謹造成的,我們更因該關心應代碼的問題--但起碼weblogic想到幫你彌補一下,是不是很貼心:)
另外一個重要功能當然是串連池監控:monitor選項卡裡可以看到使用方式,有人又要問了,沒有什麼指標啊,別忘了custom view這個功能連結哦:)
有以下指標:當前串連數、曾經達到的峰值、可以使用的串連數、等待的串連數、從資料庫開啟的串連數、曾經關閉的串連數。。。其中前3項是我最關注的
使用評價:在具體項目應用中,此串連池的持續啟動並執行穩定性很強,在大並發量的壓力下效能也相當優秀,另外在一些異常情況下串連池裡的串連也能夠及時釋放。
串連池監控一目瞭然,及時到位。
2 websphere的串連池
還是先來段題外話:記得有人說過,websphere只有版本6以後才算是websphere,個人很贊同。websphere 5以及以前的版本。。。還是忘了吧。
其實websphere的串連池秉承ibm一貫的風格:功能強大,使用複雜:)
進入控制台使用“JDBC提供者”功能菜單進行串連池的基本配置,一路下來,不同的資料庫配置方式不盡相同,最奇怪的是還要單獨手工加上user和password參數,如果沒有
資料指導的話還真是摸不著頭腦。這些基本設定還是網上找吧很多的。串連池設定完還需要設定資料來源,jndi名字一樣與之前的對應:jdbc/myapp
進階設定包括初始化串連數,最大串連,串連有效性檢查,不使用逾時。。其實這些都和weblogic中的串連池配置大致一樣。
串連池監控:使用運行監控菜單,裡邊會有一個監控項目選擇,選jdbc監控即可,可惡的是一開始彈出什麼伺服器作業系統需要安裝什麼圖形化控制項,選擇是那麼就得去找到控制項在作業系統(linux)下安裝,然後很多的相依元件都沒有。。。搞了半天才發現選擇否,監控資料以及圖形一樣能出來嘛,真是要怒了。
雖然經過一番波折但是監控的內容還是很強大的,就串連池來說一樣包括當前串連數、曾經達到的峰值、可以使用的串連數、從資料庫開啟的串連數、曾經關閉的串連數。。。其中前3項是我最關注的,比較奇怪的現象是應用剛啟動的時候已開啟的串連數量竟然沒有達到初始定義的串連數量,不清楚websphere是怎麼個電腦制。
另外在壓力大的時候可使用的串連數會是負數,當時很奇怪,想想也瞭然了,那個負數肯定是排隊等待的數量了
使用評價:在具體項目應用中,此串連池的持續啟動並執行穩定性相當強,在大並發量的壓力下效能也足夠優秀,另外在一些異常情況下串連池裡的串連能夠及時釋放,
串連池監控配置有些複雜,但是配置好後各項指標一目瞭然並且有圖形顯示
總結時刻:
這兩種商業層級的串連池都給我留下深刻印象,功能強大,使用穩定,效能優秀,監控到位。可以說難分伯仲,相對而言weblogic的串連池使用配置和監控配置更簡單明了,而websphere的更複雜但選項功能也更多一些。其實這正是對兩種應用伺服器的使用印象的直接反映,當然總體比較2種應用伺服器應該又是另一個話題了,也許在下一期的內容裡。。。
比較了多種串連池的優劣,下面這個話題可能和比較本身沒有直接關係,但個人認為應該是更有價值的一些經驗分享吧,那就是---這麼多指標配置,那些最大和最小串連數以及其他一些必要的配置指標,在一個正式的生產項目中到底應該配置什麼值呢?
其實這個值首先還是要根據具體的項目情況、資料規模以及並發數來制定的(儘管像是套話,但是我們研發人員嚴謹的作風還是必要的:)。具體而言在中型偏小型的項目--給個數值把,使用者數300到3000,資料量100萬到1億---中,建議weblogic設定為最大和最小都是200,websphere最小200最大300,前提是2者設定的最小記憶體要在1G以上,當然如果條件允許記憶體越大越好,不過32位機記憶體1.5G的限制是一定的(64位嘛我願意設個4G記憶體過來,速度提升的感覺很爽啊)。這個數字出來以後相信會有不少問題要拋過來,我一一談一下自己的體驗和想法吧
1 為什麼是200或300而不是更高?
回答: 再分配多了效果也不大了,一個是應用伺服器維持這個串連數需要記憶體支援,剛才說了32位的機器只能支援到1.5G,並且維護大量的串連進行分配使用對cpu也是一個不小的負荷,因此不宜太大。
2 為什麼不小一點?
回答: 如果太小,那麼在上述規模項目的並發量以及資料量上來以後會造成排隊現象,系統會變慢,資料庫連接會經常開啟和關閉,效能上有壓力,使用者體驗也不好。
3 為什麼weblogic最小最大都一樣,而websphere不一樣
回答: 其實和分配記憶體的最小最大值的情況一樣,一般都推薦2個值應該一致,都放在記憶體裡就好了嘛。但是ibm官方推薦2個值要有區別---官方說法還是要聽的
4 其他開源串連池的分配方案還沒說呢?
回答: 開源的個人認為到100就可以了,再高他也不會太穩定,當然1G的最小記憶體是一定要給tomcat分的
5 還有其他的指標嗎?
回答: 當然還有一些,但個人認為剩下的具體情況具體分析了不在這裡一一列舉了,大家有興趣可以和我討論分享一下。