metaclass (metaclass) wrote,
metaclass
metaclass

Сonnection pooling, JProfiler и clojure

Усиленно проверяю различные варианты пула 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

  (: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 и форумам собирать.
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 7 comments