【问题标题】:Rails Puma running out of Redis connectionsRails Puma 用完 Redis 连接
【发布时间】:2015-10-26 22:10:27
【问题描述】:

我已经查看了关于 SO 的其他类似问题,但还不能很好地组合在一起。我有一个 Rails 应用程序(在 Heroku 上),它使用 Puma 和多进程和多线程。我的应用程序还使用 Redis 作为辅助数据存储(除了 SQL 数据库),直接查询 Redis(嗯,通过 connection_pool gem)。这是我的 Puma 配置文件:

workers Integer(ENV["WEB_CONCURRENCY"] || 4)
threads_count = Integer(ENV["MAX_THREADS"] || 5)
threads threads_count, threads_count

preload_app!

rackup DefaultRackup
port ENV["PORT"] || 3000
environment ENV["RACK_ENV"] || "development"

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  ActiveRecord::Base.establish_connection

  redis_connections_per_process = Integer(ENV["REDIS_CONNS_PER_PROCESS"] || 5)
  $redis = ConnectionPool.new(size: redis_connections_per_process) do
    Redis.new(url: ENV["REDIS_URL"] || "redis://localhost:6379/0")
  end
end

我的 Redis 实例的连接限制为 20,我发现自己经常超过这个限制,尽管应该(据我所知)每个进程只有 5 个连接分布在 4 个工作进程中。

事实上,当我将REDIS_CONNS_PER_PROCESS 设置为1 时,我什至得到max number of clients reached Redis 错误。on_worker_boot 是为每个线程而不是每个进程调用的吗?

我还尝试使用单独的 redis.rb 初始化程序,即使 REDIS_CONNS_PER_PROCESS 为 1,它仍然会给我错误。这似乎很奇怪,因为如果我在做数学,我应该能够将它增加到 4正确(4 个工作进程 + 1 个主进程)* 每个进程 4 个连接。 (请注意,出于这个问题的目的,我忽略了部署过程中发生的错误,因为我假设 Heroku 可能在该过程中同时连接新旧进程,即使我没有使用 Preboot。)

我在哪里误解了这一切是如何结合在一起的?

【问题讨论】:

  • 兴趣点,为什么要同时使用进程分叉和线程?
  • 能够获得每个 Heroku dyno 的最大吞吐量。这是我基于thisthis 的理解。

标签: ruby-on-rails heroku redis connection-pooling puma


【解决方案1】:

我有类似的问题。一开始我用的是redis-togo,没问题。但是在我从 redis-togo 更改为 Heroku redis 之后,我得到了“ERR max number of clients reached”错误。

我的应用程序的代码没有改变,redis 提供者的改变是唯一的。

我在 Heroku 支持处开了一张票,他们建议我更改超时值的默认设置。

https://devcenter.heroku.com/articles/heroku-redis#configuring-your-instance

我更改了 Heroku redis 的默认超时值后,一切都解决了。 我猜redis超时的默认值因redis提供者而异。而 Heroku redis 的默认设置是 0。 “零值意味着连接不会被关闭。”

我希望我的经验对您有所帮助。

【讨论】:

  • 这真的很有帮助,谢谢!他们对我的支持请求毫无帮助,所以我很高兴 Heroku 的某个人知道如何解决这个问题。
【解决方案2】:

在进一步阅读和测试之后,我最终将我的 Redis 连接池代码移到了单独的初始化程序中。不幸的是,这根本没有解决我的问题——尽管对进程和连接号进行了很多修改,但我仍然收到max number of clients reached 错误,早于我应该的。

事实证明,答案是将 Redis 提供程序从 Heroku Redis 切换到 Redis Cloud。我不确定为什么 Heroku Redis 不允许它所宣传的连接数,但经过一些调查,Redis Cloud 实际上似乎允许 更多 个连接而不是宣传的(或至少透明地限制连接且没有错误) 没有任何问题。哇。他们肯定为我赢得了生意。

【讨论】:

  • 谢谢 - 我很高兴听到这个消息 :)
  • 老实说,我不记得上次我对基础设施产品感到欣慰、惊叹和高兴是什么时候了。向大家致敬。
  • “我不确定 Heroku Redis 为何不允许它所宣传的连接数”,他们确实如此,但你必须确保你不保留周围的空闲连接。如果你关闭它们,或者设置连接超时,Heroku redis 就会正常工作。
【解决方案3】:

我也遇到了这个问题,虽然 Heroku Redis 仪表板只显示了几个连接,但我的连接用完了。

然后我联系了 Heroku 支持,他们告诉我仪表板只显示活动的客户端/连接,而不是空闲的。

因此,由于 Redis 超时为 0(永不超时),重新启动时 Redis 连接空闲并打开新连接。所以情况每次重启都会变得更糟

正如本页其他人所提到的,一种解决方案是将超时设置为 0 以外的值:

heroku redis:timeout -s 10 -a APPLICATION_NAME

这会使连接在 10 秒后断开,这应该不是问题,因为在使用它时它会保持打开状态(没有不必要的关闭)。

当您只有很少的流量时,您可以考虑将其设置为更高的值。

【讨论】:

  • 有什么办法可以用 redis 云做同样的事情吗?
  • 您可以尝试使用redis-cli 连接到服务器,并使用config get timeout 检索当前超时,并使用config set timeout 10 设置超时。但此功能可能会被服务器禁用。
猜你喜欢
  • 2015-07-08
  • 2016-04-20
  • 2013-09-14
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
相关资源
最近更新 更多