Heroku Cedar堆栈,包含多个数据库。主数据库的RDS和第二个Analytics数据库的Postgres。服务器使用读/写RDS 和 Postgres数据库运行。在不同环境中运行的每晚rake任务需要在RDS数据库的只读从属服务器中运行特定的Resque队列。
对于记录,Postgres数据库中的所有模型都包括:
module Trove::PostgresConnection
def self.included(base)
base.class_eval do
…set up Postgres database
end
end
end
这很好用,并且作为注入每个类的模块,不会因为对ActiveRecord :: Base.connection的任何更改而被压扁
使用Heroku RDS插件定义。连接到读/写生产数据库。不幸的是,无论环境如何都使用此连接。因此,使用RAILS_ENV=analytics rake some:task
在Heroku上运行rake任务不会将此连接用于ActiveRecord::Base
:
analytics:
adapter: mysql2
encoding: utf8
database: dbase
username: uname
password: pword
host: read-only.uri.on.amazonaws.com
reconnect: true
port: 3306
相反,它使用RDS连接中提供的连接字符串:
puts Rails.env
-> 'analytics'
puts SomeModel.connection_config[:host]
-> read-write.uri.on.amazonaws.com
我花了一些时间来弄清楚这一点。自我注意:不要只看环境,看看数据库主机。
# Perform an operation using another database connection in ActiveRecord
module SwapConnection
def with_connection_to(config, &block)
ActiveRecord::Base.connection.disconnect!
ActiveRecord::Base.establish_connection(config)
yield
end
end
require 'swap_connection'
class TroveCalculations
@queue = :trove_queue
def self.perform(class_name, id)
SwapConnection.with_connection_to(Rails.env) do
Do something in a given queue
end
end
end
在Procfile中有这样的东西
troveworker: env RAILS_ENV=analytics QUEUE=trove_queue bundle exec rake resque:work
其中实际上使用该工作者的分析database.yml配置。我们目前使用此Procfile运行我们的服务器,但它仍然使用RDS数据库。
答案 0 :(得分:2)
为了扩展我对这个问题的评论,我的意思是为你的数据库添加一个“Heroku方式”的配置,然后在你的Procfile中为那个将处理该队列上的工作的一个工人引用它。
使用新名称添加配置/环境变量以及您需要的数据库配置:
heroku config:add ANALYTICS_DB=postgres://some_url
在你的Procfile
中,基于你想要的例子:
troveworker: env DATABASE_URL=$(ANALYTICS_DB) QUEUE=trove_queue \
bundle exec rake resque:work
你必须使用不同的配置为每个队列使用单独的worker,但配置将至少不在代码中。
答案 1 :(得分:1)
我只玩Heroku,但我认为数据库连接信息被Heroku工具根据heroku工具带指定的环境变量覆盖。
答案 2 :(得分:1)
这里的问题是Heroku生成自己的database.yml文件:https://devcenter.heroku.com/articles/ruby-support#build-behavior
通过使用Amazon RDS插件,Heroku设置了DATABASE_URL
环境变量。您可以通过从应用程序目录的根目录运行以下内容来查看其内容:
heroku config
此外,从Rails 3.2开始,它将使用DATABASE_URL
env var(如果设置)而不是database.yml文件:
https://github.com/mperham/sidekiq/issues/503#issuecomment-11862427
最简单的解决方法可能是:
使用Postgres连接字符串创建一个名为DATABASE_URL_ANALYTICS
的env var:
heroku config:add DATABASE_URL_ANALYTICS=postgres://xxxxxxxxxxxx
在rake文件的开头(可能发生任何rails初始化之前),添加:
ENV['DATABASE_URL'] = ENV['DATABASE_URL_ANALYTICS'] if Rails.env.analytics?
答案 3 :(得分:0)
这就是我们解决它的方式:
Procfile:
troveworker: env RAILS_ENV=analytics QUEUE=trove_queue rake trove:worker
LIB /任务/ trove.rake:
desc 'Start the Resque workers in the proper environment'
task :worker do
SwapConnection.with_connection_to Rails.env do
Rake::Task['resque:work'].invoke
end
end
此解决方案也为我们解决了一些其他问题,并且工作得非常好。谢谢大家。