ruby-on-rails – 在Puma fork之后重新连接Redis

我在rails应用程序中使用全局变量来使用redis gem存储redis客户端.在config / initializers / redis.rb中,我有

$redis = Redis.new(host: "localhost", port: 6379)

然后在应用程序代码中,我使用$redis来处理Redis存储中的数据.

我还在生产环境中使用puma作为Web服务器,并使用capistrano来部署代码.在部署过程中,capistrano重启puma.

每次我启动或重新启动美洲狮网络服务器时,当我第一次使用$redis访问Redis商店中的数据时,我总是会收到“内部服务器错误”.我看到像Redis :: InheritedError这样的错误(尝试使用来自子进程的连接而不重新连接.你需要在分叉后重新连接到Redis.)

搜索谷歌和stackoverflow让我认为我需要重新连接到美洲狮分叉子进程后重新连接到Redis.所以,我在config / puma.rb中添加了:

on_worker_boot do
  $redis.ping
end

但我仍然得到Redis :: InheritedError引起的“内部服务器错误”(尝试使用来自子进程的连接而不重新连接.您需要在分叉后重新连接到Redis.).

我看到这篇文章http://qiita.com/yaotti/items/18433802bf1720fc0c53.我接着尝试添加config / puma.rb:

on_restart do
  $redis.quit
end

那没用.

我在Redis.new之后尝试使用config / initializers / redis.rb到$redis.ping.那也行不通.

如果puma在没有运行puma进程的情况下启动,或者在运行puma进程的实例时重新启动,则会出现此错误.

刷新页面会让我超过此错误.但我想在第一次尝试使用$redis时摆脱这种情况.我以为我没有使用redis gem或正确配置其重新连接.有人能告诉我:

>这是在rails应用程序中使用redis gem的正确方法吗?
>如何在美洲狮重新连接redis连接?

puma gem文档说,“你应该放置代码来关闭这个块中的全局日志文件,redis连接等,这样它们的文件描述符就不会泄漏到重新启动的进程中.如果不这样做将导致描述符慢慢耗尽服务器多次重启时,最终会导致崩溃.“它在谈论on_restart块.但它没有说应该怎么做.

最佳答案
我能用monkeypatch修复错误.这会改变行为,因此它只是重新连接而不是抛出Redis :: InheritedError

###### MONKEYPATCH redis-rb 
# https://github.com/redis/redis-rb/issues/364
# taken from https://github.com/redis/redis-rb/pull/389/files#diff-597c124889a64c18744b52ef9687c572R314
class Redis
  class Client
   def ensure_connected
      tries = 0

      begin
        if connected?
          if Process.pid != @pid
            reconnect
          end
        else
          connect
        end

        tries += 1

        yield
      rescue ConnectionError
        disconnect

        if tries < 2 && @reconnect
          retry
        else
          raise
        end
      rescue Exception
        disconnect
        raise
      end
    end
  end
end
## MONKEYPATCH end

转载注明原文:ruby-on-rails – 在Puma fork之后重新连接Redis - 代码日志