Сonnection pooling, JProfiler и clojure
Mar. 7th, 2012 11:15 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Усиленно проверяю различные варианты пула JDBC коннектов с сервисом на кложуре.
c3p0 и серверная jvm - очень быстро растет использование памяти. Решил разобраться, поставил по совету
artureg jprofiler, подключился - внутри творится адъ.
Основное место, где выделялась память - оказалось clojure.pprint, который я использовал для отладочных логов - он массово занимался рефлекшеном, и в памяти были 100500 копий java.lang.reflect.Method. Но вроде бы их gc грохал. Ну я ее использование временно убрал, чтобы оно не заслоняло происходящее.
Потом какой-то странный эффект, что по профайлеру используемая jvm память не растет, т.е. все ок, но система показывает постоянный рост. Отключил профайлер - стало нормально, т.е. похоже, что в самом профайлере какие-то спецэффекты.
Артурег убедил меня использовать вместо с3p0 commons-dbcp, с утра сегодня откопал пример использования, завел его с firebird на жабе, затем переписал на кложурь - все работает, причем с серверной jvm, вроде бы тенденция роста есть, но очень слабая, нужно долго тестировать.
Придется видимо, проверять все комбинации: "приложение vs windows-service" "server vs client jvm" "с3p0 vs commons-dbcp vs обычный коннект без пула" и "(str ) vs clojure.pprint" и "c профайлером vs без профайлера".
Т.е. если по хорошему, 48 комбинаций, по сутки-двое тестирования на каждую, т.к. хочется как бы узнать реальную картину происходящего. Хотя для использования это все нафиг не нужно, там памяти минимум на месяц хватит даже если утечка есть (что не факт), кроме того, можно рестарт сервиса делать раз в сутки ночью (что запрещает перфекционизм).
Для засирания мозгов поисковикам еще больше, помещу тут реализацию:
http://www.developerfeed.com/jdbc/snippet/apache-dbcp-pooling-datasource-example
PS: вариант с BasicDataSource, поддерживающем проверку валидности коннекта перед отдачей его из пула:
Трасца, примеры для жабьих либ приходится по SO и форумам собирать.
c3p0 и серверная jvm - очень быстро растет использование памяти. Решил разобраться, поставил по совету
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
Основное место, где выделялась память - оказалось clojure.pprint, который я использовал для отладочных логов - он массово занимался рефлекшеном, и в памяти были 100500 копий java.lang.reflect.Method. Но вроде бы их gc грохал. Ну я ее использование временно убрал, чтобы оно не заслоняло происходящее.
Потом какой-то странный эффект, что по профайлеру используемая jvm память не растет, т.е. все ок, но система показывает постоянный рост. Отключил профайлер - стало нормально, т.е. похоже, что в самом профайлере какие-то спецэффекты.
Артурег убедил меня использовать вместо с3p0 commons-dbcp, с утра сегодня откопал пример использования, завел его с firebird на жабе, затем переписал на кложурь - все работает, причем с серверной jvm, вроде бы тенденция роста есть, но очень слабая, нужно долго тестировать.
Придется видимо, проверять все комбинации: "приложение vs windows-service" "server vs client jvm" "с3p0 vs commons-dbcp vs обычный коннект без пула" и "(str ) vs clojure.pprint" и "c профайлером vs без профайлера".
Т.е. если по хорошему, 48 комбинаций, по сутки-двое тестирования на каждую, т.к. хочется как бы узнать реальную картину происходящего. Хотя для использования это все нафиг не нужно, там памяти минимум на месяц хватит даже если утечка есть (что не факт), кроме того, можно рестарт сервиса делать раз в сутки ночью (что запрещает перфекционизм).
Для засирания мозгов поисковикам еще больше, помещу тут реализацию:
http://www.developerfeed.com/jdbc/snippet/apache-dbcp-pooling-datasource-example
(:import (org.apache.commons.pool ObjectPool)) (:import (org.apache.commons.pool.impl GenericObjectPool)) (:import (org.apache.commons.dbcp ConnectionFactory PoolingDataSource PoolableConnectionFactory DriverManagerConnectionFactory)) (def db0 (let [user (get mainConfig "firebird.user" "") rolename (get mainConfig "firebird.rolename" "") pass (get mainConfig "firebird.password" "") subname (get mainConfig "firebird.subname" "//localhost:3090/operden") encoding (get mainConfig "firebird.encoding" "WIN1251")] {:classname "org.firebirdsql.jdbc.FBDriver" :subprotocol "firebirdsql" :user user :roleName rolename :password pass :subname subname :encoding encoding})) ;;dbcp pool (defn dbcpProps [username password role] (doto (Properties.) (.put "userName" username) (.put "password" password) (.put "roleName" role)) ) (defn dbcpDataSource [spec] (let [driverClass (Class/forName "org.firebirdsql.jdbc.FBDriver") connectionPool (GenericObjectPool. nil) connectionFactory (DriverManagerConnectionFactory. (str "jdbc:" (:subprotocol spec) ":" (:subname spec)) (dbcpProps (:user spec) (:password spec) (:roleName spec)) ) poolableConnectionFactory (PoolableConnectionFactory. connectionFactory connectionPool nil nil false true) ] {:datasource (PoolingDataSource. connectionPool)}) ) (def db4 (dbcpDataSource db0))
PS: вариант с BasicDataSource, поддерживающем проверку валидности коннекта перед отдачей его из пула:
(defn dbcpBasicDataSource [spec] (let [dataSource (doto (BasicDataSource. ) (.setDriverClassName "org.firebirdsql.jdbc.FBDriver") (.setUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec))) (.setUsername (:user spec)) (.setPassword (:password spec)) (.addConnectionProperty "roleName" (:roleName spec)) (.setValidationQuery "select * from rdb$database") ) ] {:datasource dataSource}) ) (def db-dbcp-basic (dbcpBasicDataSource db0))
Трасца, примеры для жабьих либ приходится по SO и форумам собирать.
no subject
Date: 2012-03-07 08:25 am (UTC)no subject
Date: 2012-03-07 09:04 am (UTC)Похоже, без обстоятельного тестирования всех комбинаций толку не будет.
no subject
Date: 2012-03-07 09:40 am (UTC)no subject
Date: 2012-03-07 10:51 am (UTC)no subject
Date: 2012-03-07 11:07 am (UTC)no subject
Date: 2012-03-07 11:14 am (UTC)no subject
Date: 2012-03-07 10:29 pm (UTC)