【问题标题】:Is this preferred way to keep connection pool around in Ruby这是在 Ruby 中保持连接池的首选方式吗
【发布时间】:2025-12-17 12:45:02
【问题描述】:

我在 ruby​​ 方面不是很有经验(每天都用 java 编码),我正在尝试找到“Ruby 方式”来保留连接池之类的东西。我有一个带有多个线程的独立 Ruby 应用程序,我想出了类似下面的东西。

请注意,Mongo 原生 ruby​​ 驱动程序提供的 MongoClient 在内部维护连接池,所以我只需要能够保留一个 MongoClient 实例

require 'mongo'

module MongoPool

  # module instance var to ensures only one exists
  @mongo = nil

  def self.lazy_create
    @mongo ||= Mongo::MongoClient.new('localhost', 27017, :pool_size => 5, :timeout => 5)
  end

  # when getting connection lazily create pool by assigning to @mongo only if nil
  def connection
    MongoPool.lazy_create
  end

end

class PeopleRepository

  include MongoPool

  def random_person
    coll = connection['test']['people']
    coll.find_one
  end

end

# usage
PeopleRepository.new.find_one

我知道这行得通(检查了@mongoobject_id 是否在多次调用中保持不变),但这是保留事情的首选方式吗?

可能有多个存储库,因此每个存储库都可以包含MongoPool 并使用其连接。上述解决方案有什么缺点吗?还有其他我应该注意的方法吗?

注意:问题更多是关于如何以 Ruby 的方式做事,而不是关于如何做一般的事情(因为我得到了它的工作)。

【问题讨论】:

  • 这不是游泳池。这是一个单例连接。完全不同的野兽。
  • 对,我错过了池配置。问题已编辑和修复

标签: ruby mongodb module


【解决方案1】:

您实际上并不需要其他 gem 来执行此操作,实际上 Mongoid 的驱动程序 (Moped) 还不支持连接池。

类似于在 rails 中使用应用程序级常量的建议,您只需在无头应用程序中使用类变量,以便您的 MongoClient 实例在应用程序基类的所有调用中都是相同的单个对象/池实例。

例如,您可以这样做:

require 'mongo'

class MyApplication
  include Mongo

  # creates a single class instance, sets pool size but won't connect until used (lazy)
  @@client = MongoClient.new('localhost', 27017, :pool_size => 5, :connect => false)

  def do_something
    @@client['my_db']['my_collection].insert({ "foo" => "bar"})
  end
end

简单且非常直接。您上面使用的模块方法不是必需的。

您提到了 Torquebox,所以我假设您正在使用 JRuby 并让 Torquebox 为您管理应用程序的线程池。

确保您运行的是 1.8.3 版或更高版本的 mongo ruby​​ 驱动程序,其中包括一些重大修复和改进,以便在这种繁重的设置下运行。我们解决了一些线程安全问题并大大提高了连接池中的并发性。

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    假设您使用的是 Rails,我会这样做:

    # config/initializers/mongo.rb
    MONGODB = Mongo::MongoClient.new('localhost', 27017, :pool_size => 5, :timeout => 5)
    

    当您使用诸如 mongomapper 之类的库时,可能有一些方法可以配置池并透明地使用它。

    在这里查看 mongo 库:http://railscasts.com/episodes/194-mongodb-and-mongomapper

    【讨论】:

    • 不幸的是,如前所述,我没有使用 Rails 和任何其他 Web 框架。这只是一个将部署在 Torquebox 上的无头应用程序。
    • 这个例子也适用于任何 ruby​​ 设置,除了你没有把它放在初始化器中,而是放在其他地方。尽管如此,我还是建议使用更高级别的库,例如 mongoid。这实际上是“红宝石方式”。为工作使用正确的宝石!以下是如何配置它的示例:mongoid.org/en/mongoid/docs/installation.html#installation