我在尝试获取在Unicorn下运行的Rails应用程序以连接到受密码保护的Redis服务器时遇到意外和重大问题。
在命令行上使用bundle exec rails c production
,我可以通过Resque.redis发出命令。但是,当它在Unicorn下分叉时,我的配置似乎正在丢失。
使用非密码保护的Redis服务器Just Works。但是,我打算在其他服务器上运行工作程序,而不是Redis服务器所在的服务器,因此我需要密码保护。
我也成功使用密码保护(使用相同的技术)但使用Passenger而不是Unicorn。
我有以下设置:
# config/resque.yml
development: localhost:6379
test: localhost:6379
production: redis://user:PASSWORD@oak.isc.org:6379
# config/initializers/redis.rb
rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
rails_env = ENV['RAILS_ENV'] || 'development'
$resque_config = YAML.load_file(rails_root + '/config/resque.yml')
uri = URI.parse($resque_config[rails_env])
Resque.redis = Redis.new(host: uri.host, port: uri.port, password: uri.password)
# unicorn.rb bootup file
preload_app true
before_fork do |server, worker|
Redis.current.quit
end
after_fork do |server, worker|
Redis.current.quit
end
答案 0 :(得分:6)
好的,为了其他可能在谷歌上搜索这个问题的人,我至少为自己解决了这个问题
基本问题是在代码中调用Redis.new其他地方,例如。在您的地理编码器设置或独角兽配置文件中。
只需确保每次调用初始化Redis时都传递适当的值 例如
之类的东西REDIS = Redis.connect(:url => ENV['REDISTOGO_URL'])
无处不在,你永远不应该
Redis.new
因为它将默认为localhost和默认端口
答案 1 :(得分:5)
更新基于@lmarlow's comment to a resque issue的完全不同的想法。
我打赌它会在你拥有Redis的地方打破〜> 3(我的意思是ruby客户端版本,而不是服务器版本)。
在撰写本文时,Resque需要Redis~> 2,但未在其gemspec中指定。因此,您必须通过将其添加到您的Gemfile来帮助它:
gem 'redis', '~>2' # until a new version of resque comes out
gem 'resque'
此外,请确保在任何地方都使用捆绑器。否则,如果您的系统有新版本的Redis gem,它将被使用,Resque将像以前一样失败。
最后,化妆品说明......你可以将配置简化为:
# config/initializers/redis.rb
$resque_redis_url = uris_per_environment[rails_env] # note no URI.parse
Resque.redis = $resque_redis_url
然后
# unicorn.rb bootup file
after_fork do |server, worker|
Resque.redis = $resque_redis_url
end
答案 2 :(得分:2)
这对我有帮助:
来源:https://github.com/redis/redis-rb/blob/master/examples/unicorn/unicorn.rb
require "redis"
worker_processes 3
# If you set the connection to Redis *before* forking,
# you will cause forks to share a file descriptor.
#
# This causes a concurrency problem by which one fork
# can read or write to the socket while others are
# performing other operations.
#
# Most likely you'll be getting ProtocolError exceptions
# mentioning a wrong initial byte in the reply.
#
# Thus we need to connect to Redis after forking the
# worker processes.
after_fork do |server, worker|
Redis.current.quit
end
答案 3 :(得分:2)
对我来说有用的是独角兽配置:https://stackoverflow.com/a/14636024/18706
before_fork do |server, worker|
if defined?(Resque)
Resque.redis.quit
Rails.logger.info("Disconnected from Redis")
end
end
after_fork do |server, worker|
if defined?(Resque)
Resque.redis = REDIS_WORKER
Rails.logger.info("Connected to Redis")
end
end
答案 4 :(得分:0)
我认为问题出在Resque-web上。它的配置文件,他们现在修复它。在版本0.0.11中,他们也在评论中提到它:https://github.com/resque/resque-web/blob/master/config/initializers/resque_config.rb#L3
之前,他们的文件看起来像这样:https://github.com/resque/resque-web/blob/v0.0.9/config/initializers/resque_config.rb
并且,如果由于任何原因,您无法升级,那么请尝试设置env变量RAILS_RESQUE_REDIS=<host>:<port>
,因为初始化程序在尝试连接redis(并且失败)之后加载。