Resque没有使用Redis的配置设置。

7
我正在尝试让在Unicorn下运行的Rails应用连接到一个受密码保护的Redis服务器,但遇到了意外和显著的问题。
通过命令行上使用“bundle exec rails c production”,我可以通过Resque.redis发出命令。然而,当它在Unicorn下被fork时,我的配置似乎丢失了。
使用非密码保护的Redis服务器就能正常工作。但是,我打算在Redis服务器所在的其他服务器上运行workers,因此需要进行密码保护。
我还成功地使用了同样的技术来使用受密码保护的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

.

5个回答

6

为了其他可能搜索此问题的人着想,我至少已经解决了这个问题。

基本问题是在代码的其他位置调用Redis.new,例如在您的地理编码器设置或独角兽配置文件中。

只需确保每次调用initialize Redis时传递适当的值,例如类似以下内容:

REDIS = Redis.connect(:url =>  ENV['REDISTOGO_URL'])

无处不在,您永远不应该有

Redis.new 

因为默认情况下它将使用本地主机和默认端口


5
更新:完全不同的想法,基于@lmarlow在resque问题上的评论
我打赌它会在Redis ~>3(我的意思是Ruby客户端版本,而不是服务器版本)的任何地方出现故障。
截至本文撰写时,Resque需要Redis ~>2,但在其gemspec中没有指定。因此,您需要通过将以下内容添加到Gemfile来帮助它:
gem 'redis', '~>2' # until a new version of resque comes out
gem 'resque'

此外,请确保到处都在使用bundler。否则,如果您的系统有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

我已经尝试过这个方法(简化,将配置存储在全局变量中),甚至在after_fork钩子中硬编码连接字符串为Resque.redis = "redis://user:PASSWORD@oak.isc.org:6379",但是遗憾的是没有成功。Resque工作进程可以正常工作,但Rails Web应用程序无法使用它。如果我更改端口,工作进程会跟踪此更改,但应用程序不会。 - Michael Graff
如果您在生产环境下启动Rails控制台,Resque.redis的输出是什么? - Seamus Abshere
1
从控制台来看,一切都按预期运行,例如 Resque.redis.info 返回服务器的信息。如果我使用无效密码,则会收到“密码错误”样式的错误,因此我知道它在控制台上正确连接。即使在控制台上运行 Resque.redis.quit,然后再运行相同的 Resque.redis = "url" 命令也能正常工作。 - Michael Graff
我还不得不修复一些使用 ENV['RAILS_ENV'] 的例子——但由于某种原因,那并没有起作用。所以,Rails.env 解决了这个问题。此外,我不能快速重新加载 Unicorn,但完全重启也解决了这个问题。我注意到添加 gem 时也会遇到同样的问题。 - Michael Graff

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

2

对我有用的是这里的独角兽配置:https://dev59.com/cmjWa4cB1Zd3GeqPmgfG#14636024

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

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

如果由于任何原因您无法升级,则最好尝试设置环境变量RAILS_RESQUE_REDIS=<host>:<port>,因为初始化程序在尝试连接Redis(并失败)之后加载。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接