7

我在尝试让一个在 Unicorn 下运行的 Rails 应用程序连接到受密码保护的 Redis 服务器时遇到了意想不到的重大问题。

在命令行上使用bundle exec rails c production,我可以通过 Resque.redis 发出命令。但是,似乎我的配置在 Unicorn 下分叉时丢失了。

使用不受密码保护的 Redis 服务器 Just Works。但是,我打算在 Redis 服务器所在的其他服务器上运行工作程序,因此我需要对其进行密码保护。

我也成功地使用了受密码保护的密码(使用相同的技术),但使用的是乘客而不是独角兽。

我有以下设置:

# 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

.

4

5 回答 5

6

好的,为了其他可能在谷歌上搜索这个问题的人,我至少已经为自己解决了这个问题

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

只需确保每次调用初始化 Redis 时都传入适当的值,例如

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

无处不在,你不应该有

Redis.new 

因为它将默认为 localhost 和默认端口

于 2012-09-02T00:33:26.757 回答
5

更新了基于@lmarlow 对 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
于 2012-06-06T22:19:25.623 回答
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
于 2013-07-19T17:39:42.017 回答
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
于 2012-12-05T21:26:18.390 回答
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>,因为 Initializers 在尝试连接 redis(并且失败)之后正在加载。

于 2017-09-11T06:34:55.237 回答