Rails: alterna a conexão em cada solicitação, mas mantém um pool de conexão
Em nosso aplicativo Rails, precisamos usar bancos de dados diferentes, dependendo do subdomínio da solicitação (banco de dados diferente por país).
Agora estamos fazendo algo parecido com o que é recomendado emessa questão. Isto é, chamandoActiveRecord::Base.establish_connection
em cada pedido.
Masparece ActiveRecord::Base.establish_connection
desativa o conjunto de conexões atual e estabelece uma nova conexão sempre que é chamado.
Fiz este benchmark rápido para ver se havia alguma diferença significativa entre o callestablish_connection
cada vez e tendo as conexões já estabelecidas:
require 'benchmark/ips'
$config = Rails.configuration.database_configuration[Rails.env]
$db1_config = $config.dup.update('database' => 'db1')
$db2_config = $config.dup.update('database' => 'db2')
# Method 1: call establish_connection on each "request".
Benchmark.ips do |r|
r.report('establish_connection:') do
# Simulate two requests, one for each DB.
ActiveRecord::Base.establish_connection($db1_config)
MyModel.count # A little query to force the DB connection to establish.
ActiveRecord::Base.establish_connection($db2_config)
MyModel.count
end
end
# Method 2: Have different subclasses of my models, one for each DB, and
# call establish_connection only once
class MyModelDb1 < MyModel
establish_connection($db1_config)
end
class MyModelDb2 < MyModel
establish_connection($db2_config)
end
Benchmark.ips do |r|
r.report('different models:') do
MyModelDb1.count
MyModelDb2.count
end
end
Eu corro este script comrails runner
e apontando para um mysql local com alguns milhares de registros nos bancos de dados e os resultados parecem indicar que de fato existe uma grande diferença (de uma ordem de grandeza) entre os dois métodos (BTW, não tenho certeza se o benchmark é válido ou eu estraguei tudo e, portanto, os resultados são enganosos):
Calculating -------------------------------------
establish_connection: 8 i/100ms
-------------------------------------------------
establish_connection: 117.9 (±26.3%) i/s - 544 in 5.001575s
Calculating -------------------------------------
different models: 119 i/100ms
-------------------------------------------------
different models: 1299.4 (±22.1%) i/s - 6188 in 5.039483s
Então, basicamente, eu gostaria de saber se há uma maneira de manter um pool de conexão para cada subdomínio e, em seguida, reutilizar essas conexões em vez de estabelecer uma nova conexão em cada solicitação. Ter uma subclasse de meus modelos para cada subdomínio não é viável, pois há muitos modelos; Eu só quero mudar a conexão para todos os modelos (emActiveRecord::Base
)