【问题标题】:Errno::EMFILE (Too many open files - socket(2)) when using RedisStore for caching while running in PassengerErrno::EMFILE(打开的文件过多 - 套接字(2))在乘客中运行时使用 RedisStore 进行缓存
【发布时间】:2016-10-30 21:52:50
【问题描述】:

我的应用程序正在使用 redis 存储,它在本地运行良好,但在生产中,使用 Phusion Passenger(开源)我遇到了这个错误。

Errno::EMFILE (Too many open files - socket(2)):
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:24:in `initialize'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:24:in `initialize'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:143:in `new'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:143:in `connect_addrinfo'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:187:in `block in connect'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:185:in `each'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:185:in `each_with_index'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:185:in `connect'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/connection/ruby.rb:260:in `connect'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:336:in `establish_connection'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:101:in `block in connect'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:293:in `with_reconnect'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:100:in `connect'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:364:in `ensure_connected'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:221:in `block in process'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:306:in `logging'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:220:in `process'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis/client.rb:120:in `call'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis.rb:862:in `block in get'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis.rb:58:in `block in synchronize'
/usr/local/rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis.rb:58:in `synchronize'
vendor/bundle/ruby/2.2.0/gems/redis-3.3.0/lib/redis.rb:861:in `get'
vendor/bundle/ruby/2.2.0/gems/redis-store-1.1.7/lib/redis/store/interface.rb:5:in `get'
vendor/bundle/ruby/2.2.0/gems/redis-store-1.1.7/lib/redis/store/marshalling.rb:17:in `get'
vendor/bundle/ruby/2.2.0/gems/redis-activesupport-4.1.5/lib/active_support/cache/redis_store.rb:230:in `block in read_entry'
vendor/bundle/ruby/2.2.0/gems/redis-activesupport-4.1.5/lib/active_support/cache/redis_store.rb:212:in `call'
vendor/bundle/ruby/2.2.0/gems/redis-activesupport-4.1.5/lib/active_support/cache/redis_store.rb:212:in `with'
vendor/bundle/ruby/2.2.0/gems/redis-activesupport-4.1.5/lib/active_support/cache/redis_store.rb:230:in `read_entry'
vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/cache.rb:413:in `block in exist?'
vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/cache.rb:547:in `block in instrument'
vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/notifications.rb:166:in `instrument'
vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/cache.rb:547:in `instrument'
vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/cache.rb:412:in `exist?'
vendor/bundle/ruby/2.2.0/gems/redis-activesupport-4.1.5/lib/active_support/cache/redis_store.rb:200:in `exist?'

我的缓存初始化代码是

Rails.application.configure do
    Rack::MiniProfiler.config.storage_options = { host: 'redis.local.com', port: 6379 }
    Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore
    config.cache_store = :redis_store, http://redis.local.com:6379, { expires_in: 5.minutes }
    Rails.cache = ActiveSupport::Cache::RedisStore.new
end

在 redis-rb 和 redis-store gems 中搜索过,根本没有发现任何东西。 如何确保乘客在将其用作缓存存储时不会创建与 Redis 的多个连接?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 redis passenger


    【解决方案1】:

    这不是乘客问题。这是您的应用程序达到其文件描述符限制。为什么会达到极限?不知道——也许它应该打开很多文件描述符,或者你可能在某处泄漏文件描述符。您可以尝试的一件事是增加passenger_app_file_descriptor_ulimit,但这只有在您的应用程序确实应该使用许多文件描述符而不是泄漏它们时才有帮助。如果您的应用泄漏了它们,那么剩下的唯一事情就是调试您的应用,找出泄漏的来源。

    【讨论】:

    • 不能是文件描述符限制。由于缓存存储是Redis,所以没有打开文件。
    • unix 中的“文件描述符”不仅仅指文件系统上的常规文件。用于与 Redis 通信的 TCP 套接字也是文件描述符。另外,内核直接告诉您正在达到文件描述符限制(通过 EMFILES 错误代码)。所以你实际上达到了文件描述符限制。
    • 如何测试和防止达到这个限制?
    猜你喜欢
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 2023-01-09
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    相关资源
    最近更新 更多