輕鬆搞掂 clearpool:數據庫實戰教學
首先大家可能會問:現在在開源社區已有很多 database connection pooling,例如 c3p0、proxool、dbcp、bonecp、druid 和 tomcat_jdbc 等,我們還需要其它的 connection pooling 嗎?當然這些 connection pooling 都非常不錯,並且各自都有自己的優點:例如 druid 和 tomcat_jdbc 的完美性能,又例如 proxool 和 druid 的監控功能;然而它們並不是完美的,例如性能是否可再提升?如果管理分散式數據庫、如何支持分散式 Services。好的,下面就來詳細介紹 Clearpool 以及它是如何支持這些功能的。
-
如何使用 Clearpool
Clearpool 提供 ClearPoolDataSource.java,它提供兩種配置方法:配置 xml、ioc(或者通過編程實現)
這裡說下 Clearpool 和其它 database connection pooling 的不同的地方:
- 它不支持最小 connection pooling 數(min-pool-size),取而代之的是核心 connection pooling 數量(core-pool-size)
- 它不提供返回真實連接的方法,ClearPoolDataSource.java 的 getConnection() 方法返回的是數據庫連接的代理,除非利用反射機制(不建議這樣做),不然不能真正操作數據庫連接
- 它不會在獲取連接時測試連接是否有效,因為這可能會非常耗時,而它並不提供返回真實連接,所以就隔開了和數據庫連接的直接溝通,所以不用擔心會不小心關閉連接等意外情況。
-
如何配置 DataSource
Clearpool 提供三種數據配置方式:
- 配置 JDBC
- 配置 jndi
- 如果自定義的 DataSource,可以使用 DataSourceHolder.java 的 setDataSourceMap 方法來配置。
如果需要支持分散式 Services 需要配置 XADataSource 或者支持 XA 協議的 JDBC。
-
Clearpool 性能
根據測試結果:druid 和 tomcat_jdbc 的性能是非常不錯的,在某些 high concurrency 的情況下它們的性能要比其它的 connection pooling 高上十倍甚至是幾十倍。然而他們無一例外地使用了 connection pooling 鎖(ps:proxool 未使用鎖,在 high concurrency 的情況下獲取連接會導致 ArrayIndexOutOfBoundsException),那如果我們不使用鎖的話,就是肯定能提高性能嗎?是的,這是當然。Clearpool 並沒有使用任何鎖機制,而且不會導致任何數據越界異常,它的秘訣就是使用 Atomic 操作代替了鎖。然而 AtomicSingleChain.java 使用了 sun.misc.Unsafe.java,或許比較保守的你會說這是一種冒險的做法,是的,或許以後 oracle 會拋棄 Unsafe.java,不過沒關系,這我們可以使用它的替身 LockSingleChain.java,這是一個普通、使用鎖的 connection pooling。下面來看看 Clearpool 和 druid、tomcat_jdbc 的性能比較結果(最大連接數為 50、最小連接數為 20、線程數為 100):
數據庫 connection poolingClearpool 功能和配置詳解
上圖比較的是 high concurrency 下獲取連接時的性能,如果需要測試 high concurrency 下的 DML,Clearpool 的性能就和 druid、tomcat_jdbc 差不多,原因在於 Clearpool 使用 Dynamic Proxy 產生 Statement,Dynamic Proxy 產生位元組碼時會比較耗時,而產生的位元組碼會作為WeakReference 緩存,而 high concurrency 下會多次啟動 gc,從而會多次回收並多次生成 Statement 代理的位元組碼,所以就影響了測試結果(詳細情況請參見 JDK 的java.lang.reflect.Proxy.java 源碼)。而 druid 和 tomcat_jdbc 使用的是普通的 Static Proxy,所以沒有這個問題。Clearpool 使用 Dynamic Proxy 的原因主要是為了減少代碼量,如果使用 Static Proxy,至少需要三個 Proxy 類(Statement、PreparedStatement 和 CallableStatement)以及它們的所有方法。而使用 Dynamic Proxy 只需要一個handler就足夠了。
-
管理分散式數據庫池和 JTA
Clearpool 可以管理分散式數據庫,配置分散式 connection pooling 時我們需要做的只是配置多個<distribute-url>標簽(xml 配置)或者初始化多個 connection pooling(IOC 或編程)。Clearpool 會根據配置自動管理所有 connection pooling:如多餘空間連接的回收、無效連接的重置、數據庫池的監控等等。Clearpool 還提供了支持 JTA 的入口類:UserTransactionImpl.java,我們可以像下面這樣簡單地使用分散式 Services(con1 和 con2 取自數據庫 connection pooling):
UserTransaction tx = new UserTransactionImpl(); Statement st1 = con1.createStatement(); Statement st2 = con2.createStatement(); tx.begin(); try{ st1 .execute(“insert**”); st2 .execute(“update**”); tx.commit(); }catch(Throwable t){ ts.roolback(); }
-
如何監控數據庫 connection pooling
如果想監控數據庫 connection pooling,則需要配置<console>(xml 配置)或者設置ClearPoolDataSource 的 Console,我們可以通過<console>的<port>配置端口、通過<console>的<port>的<security>配置用戶名和密碼;如果需要列出 sql,則需要配置<show-sql>為 true 或者設置 ClearPoolDataSource 的setShowSql(true) 方法,同時需要啟用日誌功能(classpath 中加入 commons-logging.jar 即可)。 PreparedStatement s = conn.prepareStatement(“select 1 from ?”); s.setString(1, “hello”); s.execute(); s.close();
-
其它
Clearpool 本身不提供 log 功能,但也可以列出日誌,它並不像 proxool 那樣會強制把commons-logging.jar 的代碼加竹 proxool.jar,而是可以和 commons-logging 無縫連接,如果想要列出日誌只需要引入 commons-logging.jar 即可。好吧,“Clearpool 並不產生日誌,它只是日誌的搬運工”。Clearpool 代碼量十分地少,jar 包只有 100KB 左右,非常易於使用,相信你都能非常快地掌握它吧。
下載