Как обойти ошибку CachedConnectionManager на JBoss с JRuby? - PullRequest
4 голосов
/ 25 января 2012

У меня проблема с развертыванием приложения JRuby Rails в JBoss с использованием JNDI для управления соединениями с базой данных.После первого запроса у меня появляется эта ошибка:

[CachedConnectionManager] Closing a connection for you.  Please close them yourself

Я думаю, это потому, что JBoss использует пул соединений и ожидает, что rails (jruby) освобождает соединение после каждого использования, что не так, потому что rails (ActiveRecord) имеет собственный пул подключений.

Я пытался звонить

ActiveRecord::Base.clear_active_connections!

после каждого запроса, в after_filter, но это не сработало.

У кого-нибудь есть идеи?

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 17 мая 2012

У меня также возникают проблемы с пулом соединений при попытке запустить приложение Sinatra / ActiveRecord в многопоточном режиме в контейнере Glassfishv3. Приложение включает блок «before» с ActiveRecord::Base.connection для принудительного получения подключения, принадлежащего потоку, и блок «after» с ActiveRecord::Base.clear_active_connections! для освобождения этого подключения.

Многопоточный режим

Я испробовал множество вариантов ActiveRecord 3.0.12 и 3.2.3, JNDI с пулом соединений Glassfish, просто используя пул соединений ActiveRecord или даже обезьяны, исправляющие пул соединений ActiveRecord, чтобы полностью обойти его, используя пул Glassfish непосредственно.

При тестировании с использованием простого многопоточного сборщика HTTP все варианты, которые я пробовал, приводили к ошибкам с большим процентом неудачных запросов при увеличении рабочих потоков в сборщике HTTP.

В AR 3.0.12 типичной ошибкой является то, что пул Glassfish выдает исключение тайм-аута (для чего бы то ни было, мой пул AR-подключений больше, чем мой Glassfish-пул; я понимаю, что AR будет объединять объект адаптера соединения, а arjdbc будет получить и выпустить реальные связи за кулисами).

С AR 3.2.3 я получаю более зловещую ошибку. Приведенная ниже ошибка возникла в результате теста, в котором не использовался JNDI, а просто использовался пул соединений ActiveRecord. Это одна из лучших конфигураций, в которой около 95% запросов выполняются нормально. Запросы об ошибках завершаются с этим исключением:

org.jruby.exceptions.RaiseException: (ConcurrencyError) Detected invalid hash contents due to unsynchronized modifications with concurrent users
    at org.jruby.RubyHash.keys(org/jruby/RubyHash.java:1356)
    at ActiveRecord::ConnectionAdapters::ConnectionPool.release(/Users/pat/app/glassfish/glassfish3/glassfish/domains/domain1/applications/lookup_service/WEB-INF/gems/gems/activerecord-3.2.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:294)
    at ActiveRecord::ConnectionAdapters::ConnectionPool.checkin(/Users/pat/app/glassfish/glassfish3/glassfish/domains/domain1/applications/lookup_service/WEB-INF/gems/gems/activerecord-3.2.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:282)
    at MonitorMixin.mon_synchronize(classpath:/META-INF/jruby.home/lib/ruby/1.9/monitor.rb:201)
    at MonitorMixin.mon_synchronize(classpath:/META-INF/jruby.home/lib/ruby/1.9/monitor.rb:200)
    at ActiveRecord::ConnectionAdapters::ConnectionPool.checkin(/Users/pat/app/glassfish/glassfish3/glassfish/domains/domain1/applications/lookup_service/WEB-INF/gems/gems/activerecord-3.2.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:276)
    at ActiveRecord::ConnectionAdapters::ConnectionPool.release_connection(/Users/pat/apps/glassfish/glassfish3/glassfish/domains/domain1/applications/lookup_service/WEB-INF/gems/gems/activerecord-3.2.3/lib/active_record/connection_adapters/abstrac/connection_pool.rb:110)
    at ActiveRecord::ConnectionAdapters::ConnectionHandler.clear_active_connections!(/Users/pat/apps/glassfish/glassfish3/glassfish/domains/domain1/applications/lookup_service/WEB-INF/gems/gems/activerecord-3.2.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:375)
    ...

однопоточный режим

Потеряв уверенность в общей безопасности потоков ActiveRecord (или arjdbc?), Я отказался от использования многопоточного и сконфигурированного warbler ActiveRecord и JRuby-Rack для создания пула времени выполнения JRuby , эмулируя несколько однопоточных процессов Ruby так же, как Unicorn, Thin и другие типичные серверы Ruby.

В config / warble.rb:

  config.webxml.jruby.min.runtimes = 10
  config.webxml.jruby.max.runtimes = 10

Я перезапустил свой тест, используя на этот раз JNDI, и все запросы были выполнены без ошибок!

Мой пул соединений Glassfish имеет размер 5. Обратите внимание, что количество рабочих циклов jruby больше, чем размер пула соединений. Вероятно, нет смысла делать пул времени выполнения JRuby больше пула соединений с базой данных, поскольку в этом приложении каждый запрос использует соединение с базой данных, но я просто хотел убедиться, что даже при конфликте за соединения с базой данных я не получил время. ошибки, которые я видел в многопоточном режиме.

Эти проблемы параллелизма неутешительны, если не сказать больше. Кто-нибудь успешно использует ActiveRecord при умеренном параллелизме? Я знаю, что в приложении Rails нужно вызывать config.threadsafe!, чтобы избежать глобальной блокировки. Глядя на код, он, похоже, не изменяет никаких настроек ActiveRecord; Есть ли какая-то конфигурация ActiveRecord, которой я не занимаюсь?

0 голосов
/ 22 марта 2012

Пул соединений Rails держит соединения открытыми, даже после того, как они возвращаются в пул, поэтому базовое соединение JDBC не закрывается.Используете ли вы JNDI-соединение с activerecord-jdbc-адаптером (adapter: jndi или jndi: location в database.yml)?

Если это так, то должно произойти автоматически и будетошибка.

Если нет, вы можете использовать код в ar-jdbc и самостоятельно применить соответствующие обратные вызовы пула соединений.

https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/jdbc/callbacks.rb

class ActiveRecord::ConnectionAdapters::JdbcAdapter
  # This should force every connection to be closed when it gets checked back
  # into the connection pool
  include ActiveRecord::ConnectionAdapters::JndiConnectionPoolCallbacks
end
...