文档菜单
文档首页
/ / /
Mongoid
/

配置

在本页

  • 生成默认配置
  • 加载 Mongoid 配置
  • Mongoid 配置选项
  • 基于版本默认
  • ERb 预处理
  • 日志记录
  • 在 Ruby on Rails 应用程序中
  • 独立
  • 时区
  • 设置从 MongoDB 加载数据的时区
  • 配置SSLContext
  • 网络压缩
  • 客户端加密
  • 与分叉服务器一起使用
  • Puma
  • Unicorn
  • Passenger
  • 查询缓存中间件
  • 为 Rack 网络请求启用查询缓存
  • 为 ActiveJob 启用查询缓存
  • 开发配置

Mongoid 通常通过mongoid.yml 文件用于指定选项和客户端。最简单的配置如下,它配置Mongoid与运行在 "localhost:27017" 的MongoDB服务器通信,并使用名为 "mongoid" 的数据库。

development:
clients:
default:
database: mongoid
hosts:
- localhost:27017

配置文件中的顶级键,如上述示例中的 development,表示应用程序正在执行的环境名称,即 developmenttestproduction。上述示例中的第三级键 default 指的是Mongo客户端名称。大多数应用程序将使用一个名为 default 的单个客户端。

如果您正在使用Ruby on Rails,可以通过运行以下命令让Mongoid为您生成默认配置文件:

rails g mongoid:config

配置文件将被放置在 config/mongoid.yml 中。同时还会创建一个初始化器并放置在 config/initializers/mongoid.rb 中。建议将所有配置都指定在 config/mongoid.yml 中,但如果您愿意,也可以使用 mongoid.rb 初始化器来设置配置选项。但请注意,mongoid.yml 中的设置始终优先于初始化器中的设置。

如果您不使用Ruby on Rails,可以将上述给出的最小配置复制并保存为 config/mongoid.yml

如果您正在使用Ruby on Rails,Mongoid配置将在应用程序加载时自动加载,加载的配置存储在 Rails.env 中。

您可能需要配置您的应用程序以使用Mongoid ORM,可以通过在application.rb中添加以下内容来实现。

config.generators do |g|
g.orm :mongoid
end

如果您不使用Ruby on Rails,则必须手动加载Mongoid配置。这可以通过Mongoid.load!方法完成,该方法需要一个配置文件路径作为其参数,如下所示

# Use automatically detected environment name
Mongoid.load!("path/to/your/mongoid.yml")
# Specify environment name manually
Mongoid.load!("path/to/your/mongoid.yml", :production)

当Mongoid被要求自动检测环境名称时,它会按照以下顺序检查以下来源

  • 如果定义了Rails顶级常量,则为Rails.env

  • 如果定义了Sinatra顶级常量,则为Sinatra::Base.environment

  • RACK_ENV环境变量。

  • MONGOID_ENV环境变量。

您还可以直接在Ruby中配置Mongoid,而无需使用配置文件。这种配置样式不支持环境的概念 - 提供的任何配置都将应用于当前环境 - 但它支持定义多个客户端。

Mongoid.configure do |config|
config.clients.default = {
hosts: ['localhost:27017'],
database: 'my_db',
}
config.log_level = :warn
end

注意

Mongoid必须在任何组件被使用或引用之前进行配置。一旦组件被使用或引用,更改配置可能不会应用于已经实例化的组件。

以下带有注释的示例mongoid.yml演示了如何配置Mongoid。

Mongoid将客户端配置委托给Ruby驱动程序。请参阅驱动程序文档以获取有关驱动程序选项的详细信息。

development:
# Configure available database clients. (required)
clients:
# Defines the default client. (required)
default:
# Mongoid can connect to a URI accepted by the driver:
# uri: mongodb://user:password@mongodb.domain.com:27017/my_db_development
# Otherwise define the parameters separately.
# This defines the name of the default database that Mongoid can connect to.
# (required).
database: my_db_development
# Provides the hosts the default client can connect to. Must be an array
# of host:port pairs. (required)
hosts:
- localhost:27017
options:
# Note that all options listed below are Ruby driver client options (the mongo gem).
# Please refer to the driver documentation of the version of the mongo gem you are using
# for the most up-to-date list of options.
# Change the default write concern. (default = { w: 1 })
# write:
# w: 1
# Change the default read preference. Valid options for mode are: :secondary,
# :secondary_preferred, :primary, :primary_preferred, :nearest
# (default: primary)
# read:
# mode: :secondary_preferred
# tag_sets:
# - use: web
# The name of the user for authentication.
# user: 'user'
# The password of the user for authentication.
# password: 'password'
# The user's database roles.
# roles:
# - 'dbOwner'
# Change the default authentication mechanism. Valid options include:
# :scram, :scram256, :mongodb_cr, :mongodb_x509, :gssapi, :aws, :plain.
# MongoDB Server defaults to :scram, which will use "SCRAM-SHA-256" if available,
# otherwise fallback to "SCRAM-SHA-1" (:scram256 will always use "SCRAM-SHA-256".)
# This setting is handled by the MongoDB Ruby Driver. Please refer to:
# https://mongodb.ac.cn/docs/ruby-driver/current/reference/authentication/
# auth_mech: :scram
# The database or source to authenticate the user against.
# (default: the database specified above or admin)
# auth_source: admin
# Force a the driver cluster to behave in a certain manner instead of auto-
# discovering. Can be one of: :direct, :replica_set, :sharded. Set to :direct
# when connecting to hidden members of a replica set.
# connect: :direct
# Changes the default time in seconds the server monitors refresh their status
# via hello commands. (default: 10)
# heartbeat_frequency: 10
# The time in seconds for selecting servers for a near read preference. (default: 0.015)
# local_threshold: 0.015
# The timeout in seconds for selecting a server for an operation. (default: 30)
# server_selection_timeout: 30
# The maximum number of connections in the connection pool. (default: 5)
# max_pool_size: 5
# The minimum number of connections in the connection pool. (default: 1)
# min_pool_size: 1
# The time to wait, in seconds, in the connection pool for a connection
# to be checked in before timing out. (default: 5)
# wait_queue_timeout: 5
# The time to wait to establish a connection before timing out, in seconds.
# (default: 10)
# connect_timeout: 10
# How long to wait for a response for each operation sent to the
# server. This timeout should be set to a value larger than the
# processing time for the longest operation that will be executed
# by the application. Note that this is a client-side timeout;
# the server may continue executing an operation after the client
# aborts it with the SocketTimeout exception.
# (default: nil, meaning no timeout)
# socket_timeout: 5
# The name of the replica set to connect to. Servers provided as seeds that do
# not belong to this replica set will be ignored.
# replica_set: name
# Compressors to use for wire protocol compression. (default is to not use compression)
# "zstd" requires zstd-ruby gem. "snappy" requires snappy gem.
# Refer to: https://mongodb.ac.cn/docs/ruby-driver/current/reference/create-client/#compression
# compressors: ["zstd", "snappy", "zlib"]
# Whether to connect to the servers via ssl. (default: false)
# ssl: true
# The certificate file used to identify the connection against MongoDB.
# ssl_cert: /path/to/my.cert
# The private keyfile used to identify the connection against MongoDB.
# Note that even if the key is stored in the same file as the certificate,
# both need to be explicitly specified.
# ssl_key: /path/to/my.key
# A passphrase for the private key.
# ssl_key_pass_phrase: password
# Whether to do peer certification validation. (default: true)
# ssl_verify: true
# The file containing concatenated certificate authority certificates
# used to validate certs passed from the other end of the connection.
# ssl_ca_cert: /path/to/ca.cert
# Whether to truncate long log lines. (default: true)
# truncate_logs: true
# Configure Mongoid-specific options. (optional)
options:
# Allow BSON::Decimal128 to be parsed and returned directly in
# field values. When BSON 5 is present and the this option is set to false
# (the default), BSON::Decimal128 values in the database will be returned
# as BigDecimal.
#
# @note this option only has effect when BSON 5+ is present. Otherwise,
# the setting is ignored.
# allow_bson5_decimal128: false
# Application name that is printed to the MongoDB logs upon establishing
# a connection. Note that the name cannot exceed 128 bytes in length.
# It is also used as the database name if the database name is not
# explicitly defined. (default: nil)
# app_name: nil
# When this flag is false, callbacks for embedded documents will not be
# called. This is the default in 9.0.
#
# Setting this flag to true restores the pre-9.0 behavior, where callbacks
# for embedded documents are called. This may lead to stack overflow errors
# if there are more than cicrca 1000 embedded documents in the root
# document's dependencies graph.
# See https://jira.mongodb.org/browse/MONGOID-5658 for more details.
# around_callbacks_for_embeds: false
# Sets the async_query_executor for the application. By default the thread pool executor
# is set to `:immediate`. Options are:
#
# - :immediate - Initializes a single +Concurrent::ImmediateExecutor+
# - :global_thread_pool - Initializes a single +Concurrent::ThreadPoolExecutor+
# that uses the +async_query_concurrency+ for the +max_threads+ value.
# async_query_executor: :immediate
# Mark belongs_to associations as required by default, so that saving a
# model with a missing belongs_to association will trigger a validation
# error.
# belongs_to_required_by_default: true
# Set the global discriminator key.
# discriminator_key: "_type"
# Raise an exception when a field is redefined.
# duplicate_fields_exception: false
# Defines how many asynchronous queries can be executed concurrently.
# This option should be set only if `async_query_executor` is set
# to `:global_thread_pool`.
# global_executor_concurrency: nil
# When this flag is true, any attempt to change the _id of a persisted
# document will raise an exception (`Errors::ImmutableAttribute`).
# This is the default in 9.0. Setting this flag to false restores the
# pre-9.0 behavior, where changing the _id of a persisted
# document might be ignored, or it might work, depending on the situation.
# immutable_ids: true
# Include the root model name in json serialization.
# include_root_in_json: false
# # Include the _type field in serialization.
# include_type_for_serialization: false
# Whether to join nested persistence contexts for atomic operations
# to parent contexts by default.
# join_contexts: false
# When this flag is false (the default as of Mongoid 9.0), a document that
# is created or loaded will remember the storage options that were active
# when it was loaded, and will use those same options by default when
# saving or reloading itself.
#
# When this flag is true you'll get pre-9.0 behavior, where a document will
# not remember the storage options from when it was loaded/created, and
# subsequent updates will need to explicitly set up those options each time.
#
# For example:
#
# record = Model.with(collection: 'other_collection') { Model.first }
#
# This will try to load the first document from 'other_collection' and
# instantiate it as a Model instance. Pre-9.0, the record object would
# not remember that it came from 'other_collection', and attempts to
# update it or reload it would fail unless you first remembered to
# explicitly specify the collection every time.
#
# As of Mongoid 9.0, the record will remember that it came from
# 'other_collection', and updates and reloads will automatically default
# to that collection, for that record object.
# legacy_persistence_context_behavior: false
# When this flag is false, a document will become read-only only once the
# #readonly! method is called, and an error will be raised on attempting
# to save or update such documents, instead of just on delete. When this
# flag is true, a document is only read-only if it has been projected
# using #only or #without, and read-only documents will not be
# deletable/destroyable, but they will be savable/updatable.
# When this feature flag is turned on, the read-only state will be reset on
# reload, but when it is turned off, it won't be.
# legacy_readonly: false
# The log level.
#
# It must be set prior to referencing clients or Mongo.logger,
# changes to this option are not be propagated to any clients and
# loggers that already exist.
#
# Additionally, only when the clients are configured via the
# configuration file is the log level given by this option honored.
# log_level: :info
# Store BigDecimals as Decimal128s instead of strings in the db.
# map_big_decimal_to_decimal128: true
# Preload all models in development, needed when models use inheritance.
# preload_models: false
# When this flag is true, callbacks for every embedded document will be
# called only once, even if the embedded document is embedded in multiple
# documents in the root document's dependencies graph.
# This is the default in 9.0. Setting this flag to false restores the
# pre-9.0 behavior, where callbacks are called for every occurrence of an
# embedded document. The pre-9.0 behavior leads to a problem that for multi
# level nested documents callbacks are called multiple times.
# See https://jira.mongodb.org/browse/MONGOID-5542
# prevent_multiple_calls_of_embedded_callbacks: true
# Raise an error when performing a #find and the document is not found.
# raise_not_found_error: true
# Raise an error when defining a scope with the same name as an
# existing method.
# scope_overwrite_exception: false
# Return stored times as UTC.
# use_utc: false
# Configure Driver-specific options. (optional)
driver_options:
# When this flag is off, an aggregation done on a view will be executed over
# the documents included in that view, instead of all documents in the
# collection. When this flag is on, the view filter is ignored.
# broken_view_aggregate: true
# When this flag is set to false, the view options will be correctly
# propagated to readable methods.
# broken_view_options: true
# When this flag is set to true, the update and replace methods will
# validate the parameters and raise an error if they are invalid.
# validate_update_replace: false

Mongoid支持将配置选项设置为特定版本的默认值。这对于升级到新的Mongoid版本很有用。在升级Mongoid版本时,应在Mongoid::Config上设置以下内容

Mongoid.configure do |config|
config.load_defaults <OLD VERSION>
end

这样,当升级到Mongoid的新版本时,您的代码将使用Mongoid旧版本的配置选项运行。然后,您可以逐个更改新版本的特性标志,并测试您的代码是否仍然按预期工作。一旦所有新的特性标志都已考虑在内,对load_defaults的调用可以改为接受版本,并删除所有更改的特性标志。

例如,假设我们正在从7.5升级到8.0。在这两个版本之间,添加了两个特性标志:legacy_attributesmap_big_decimal_to_decimal128。在升级到Mongoid 8之前,请将以下内容添加到您的Mongoid::Config

Mongoid.configure do |config|
config.load_defaults 7.5
end

在您的Gemfile中升级到Mongoid 8.0后,任何特性标志都将保留为7.5的默认行为:legacy_attributes: true, map_big_decimal_to_decimal128: false。然后,您可以逐个将特性标志更改为8.0的行为

Mongoid.configure do |config|
config.load_defaults 7.5
config.legacy_attributes = false
# config.map_big_decimal_to_decimal128 = true
end

我们建议逐个进行这些更改,因此在上面的示例中,我们留下了第二个标志的注释。在确认您的代码在关闭legacy_attributes标志后仍然按预期工作后,可以取消注释map_big_decimal_to_decimal128设置。一旦该功能也得到验证,这两行都可以删除,并用以下内容替换load_defaults

Mongoid.configure do |config|
config.load_defaults 8.0
end

当加载配置文件时,Mongoid会在将其解析为YAML之前用ERb处理它。这允许根据环境变量在运行时构建配置文件的内容。

development:
clients:
default:
uri: "<%= ENV['MONGODB_URI'] %>"

注意

当从ERb输出值时,请确保值是有效的YAML,并按需转义。

注意

由于ERb渲染在YAML解析之前执行,因此配置文件中的所有ERb指令都会被评估,包括出现在YAML注释中的指令。

当配置日志记录时,重要的是要注意Mongoid在MongoDB Ruby驱动程序之上提供了一个模型层,并且驱动程序将CRUD操作调度到MongoDB部署。因此,使用Mongoid的应用程序中的一些日志输出来自Mongoid本身,而另一些来自驱动程序。

mongo客户端是一个Ruby驱动客户端实例,因此mongo客户端的日志记录器是Ruby驱动日志记录器,而不是Mongoid日志记录器。换句话说

# Ruby driver logger, not Mongoid logger
Mongoid.client(:default).logger

根据是否在Ruby on Rails应用程序中使用Mongoid,以及Mongoid和Ruby驱动如何配置,它们可能使用相同的日志记录器实例或不同的实例,可能具有不同的配置。

当在Ruby on Rails应用程序中使用时,Mongoid默认继承Rails的日志记录器和日志级别,并将驱动程序日志记录器设置为相同的日志记录器实例

Rails.logger === Mongoid.logger
# => true
Mongoid.logger === Mongo::Logger.logger
# => true

要更改日志级别,使用标准的Rails配置。将以下内容放入环境配置文件之一中,例如config/environments/production.rb

Rails.application.configure do
config.log_level = :debug
end

注意

当Mongoid在Rails应用程序中运行时,不使用log_level Mongoid配置选项,因为在这种情况下Mongoid继承了Rails的日志级别。

要使用初始化器将Mongoid或驱动程序日志记录器配置为与Rails日志记录器不同,请按照以下方式进行

Rails.application.configure do
config.after_initialize do
# Change Mongoid log destination and/or level
Mongoid.logger = Logger.new(STDERR).tap do |logger|
logger.level = Logger::DEBUG
end
# Change driver log destination and/or level
Mongo::Logger.logger = Logger.new(STDERR).tap do |logger|
logger.level = Logger::DEBUG
end
end
end

注意

目前,在Ruby标准库Logger中没有提供返回日志设备(即IO对象)的方法。例如,为了使Mongoid和/或Ruby驱动程序将日志记录到标准的Rails日志文件(例如log/development.log),但使用与标准Rails日志记录器(《code class="leafygreen-ui-1l06pbn">Rails.logger)不同的级别,必须单独打开该文件,并将得到的IO对象传递给Logger构造函数。

注意

由于Mongoid默认将其自己的记录器和驱动器的记录器设置为与Rails记录器相同的实例,因此修改任何实例都会影响所有实例。例如,以下更改了所有三个记录器的日志级别,除非应用程序已如上所述分配了单独的Logger实例给Mongo::Logger.logger

Mongoid::Logger.logger.level = Logger::DEBUG

当不在Ruby on Rails应用程序中加载时,Mongoid会尊重log_level顶级配置选项。它可以在配置文件中按如下方式提供

development:
clients:
default:
# ...
options:
log_level: :debug

... 或者当配置Mongoid时

Mongoid.configure do |config|
config.log_level = :debug
end

Mongoid 7.1及更高版本的默认日志目的地是标准错误。Mongoid 7.0及更低版本的默认日志目的地是标准输出。要更改日志目的地,创建一个新的记录器实例如下

Mongoid.logger = Logger.new(STDERR).tap do |logger|
logger.level = Logger::DEBUG
end

要更改Ruby驱动器日志级别或目的地

Mongo::Logger.logger = Logger.new(STDERR).tap do |logger|
logger.level = Logger::DEBUG
end

要将驱动器记录器设置为与Mongoid记录器相同

Mongo::Logger.logger = Mongoid.logger

注意

Mongoid在独立模式下运行时不会更改驱动器的记录器。

Mongoid使用ActiveSupport的时间功能,这比Ruby的标准库要强大得多。重要的是,ActiveSupport允许配置Time.zone,一个线程全局变量,它为处理日期和时间值提供上下文。

虽然对Ruby中时区的全面处理超出了本教程的范围,但实现正确时区处理的简单且可靠的方法如下

  1. 将操作系统的时区设置为UTC。例如,在Linux上

cp /usr/share/zoneinfo/UTC /etc/localtime
  1. 将应用程序默认时区设置为UTC

# If using Rails, in application.rb:
class Application < Rails::Application
config.time_zone = 'UTC'
end
# If not using Rails:
Time.zone = 'UTC'
  1. 在每个控制器和作业类中,尽可能早地在before_filter中设置适当的时间区。例如,如果应用程序的每个用户都可以设置自己的时区,你可能希望这样做

class ApplicationController < ActionController::Base
before_filter :fetch_user,
:set_time_zone
def set_time_zone
Time.zone = @user.time_zone
end
end
  1. 从这里,你可以在本地时区中自然地处理时间。例如,在一个视图中

Turned into a pumpkin after <%= cinderella.updated_at.seconds_after_midnight %> seconds!
  1. 使用ActiveSupport方法而不是Ruby标准库。

    • Time.zone.nowTime.current`而不是`Time.now

    • Date.current而不是Date.today

    关键要注意,后者Ruby标准库方法引用的是您的系统时区(例如UTC),而不是Time.zone的值。由于这些方法名称相似,很容易混淆,我们建议在您的CI中使用Rubocop的Rails/TimeZone cop

MongoDB将所有时间存储在UTC中,不包含时区信息。Mongoid模型加载和返回时间值作为ActiveSupport::TimeWithZone的实例。您可以将use_utc选项设置为控制Mongoid在从数据库加载时如何设置时区。

  • 如果为false(默认),Mongoid将使用Time.zone来设置从数据库加载的时间值时的时间区。

  • 如果为true,Mongoid将始终将UTC设置为加载时间值的时间区。

use_utc仅影响数据的加载方式,不影响数据的持久化。例如,如果您将TimeActiveSupport::TimeWithZone实例分配给时间字段,则分配实例的时间区信息始终会被使用,不受use_utc设置的约束。或者,如果您将字符串值分配给时间字段,如果字符串中存在时区信息,则使用该信息。如果字符串不包含时区信息,则将其解析为Time.zone。为了说明

Time.use_zone("Asia/Kolkata") do
# String does not include time zone, so "Asia/Kolkata" will be used
ghandi.born_at = "1869-10-02 7:10 PM"
# Time zone in string (-0600) will be used
amelia.born_at = "1897-07-24 11:30 -0600"
end

您可能希望进一步配置应用程序中的TLS选项,例如通过启用或禁用某些加密算法。

这可以通过在Ruby驱动程序上设置TLS上下文钩子来实现 -- TLS上下文钩子是用户提供的 Proc(s),将在驱动程序中的任何TLS套接字连接之前调用,并可用于修改套接字使用的底层 OpenSSL::SSL::SSLContext 对象。

要设置TLS上下文钩子,将 Proc(s) 添加到 Mongo.tls_context_hooks 数组中。这可以在初始化器中完成。下面的示例添加了一个钩子,该钩子仅启用 "AES256-SHA" 加密算法。

Mongo.tls_context_hooks.push(
Proc.new { |context|
context.ciphers = ["AES256-SHA"]
}
)
# Only the AES256-SHA cipher will be enabled from this point forward

Mongo.tls_context_hooks 中的每个 Proc 都将传递一个 OpenSSL::SSL::SSLContext 对象作为其唯一的参数。这些过程将在创建套接字期间按顺序执行。

警告

TLS上下文钩子是全局的,将影响应用程序中所有 Mongo::Client 实例。

有关TLS上下文钩子的更多信息,包括分配和删除的最佳实践,请参阅 Ruby驱动程序文档

Mongoid 支持对从MongoDB服务器发送和接收的消息进行压缩。此功能由Ruby驱动程序提供,该驱动程序实现了MongoDB服务器支持的三种算法。

  • Snappy:从3.4版本开始,连接到MongoDB服务器时可以使用Snappy压缩,需要安装Snappy库。

  • Zlib:从3.6版本开始,连接到MongoDB服务器时可以使用Zlib压缩。

  • Zstandard:从4.2版本开始,连接MongoDB服务器时可以使用zstd压缩,并需要安装zstd-ruby库。

要使用线协议压缩,请在mongoid.yml中配置Ruby驱动程序选项。

development:
# Configure available database clients. (required)
clients:
# Define the default client. (required)
default:
# ...
options:
# These options are Ruby driver options, documented in
# https://mongodb.ac.cn/docs/ruby-driver/current/reference/create-client/
# ...
# Compressors to use. (default is to not use compression)
# Valid values are zstd, zlib or snappy - or any combination of the three
compressors: ["zstd", "snappy"]

如果没有明确请求压缩程序,即使系统上存在一个或多个压缩程序所需的依赖项,驱动程序也不会使用压缩。

驱动程序选择请求的压缩程序列表中第一个同时由服务器支持的压缩程序。建议使用zstd压缩程序,因为它与其他压缩程序相比,在相同的CPU消耗下提供最高的压缩率。

为了与服务器具有最大兼容性,可以指定所有三个压缩程序,例如,作为compressors: ["zstd", "snappy", "zlib"]

当加载配置文件时,Mongoid 允许文件包含用于指定客户端加密模式中模式映射的keyIdBSON::Binary实例,如下例所示

development:
clients:
default:
database: blog_development
hosts: [localhost:27017]
options:
auto_encryption_options:
key_vault_namespace: 'keyvault.datakeys'
kms_providers:
local:
key: "z7iYiYKLuYymEWtk4kfny1ESBwwFdA58qMqff96A8ghiOcIK75lJGPUIocku8LOFjQuEgeIP4xlln3s7r93FV9J5sAE7zg8U"
schema_map:
blog_development.comments:
properties:
message:
encrypt:
keyId:
- !ruby/object:BSON::Binary
data: !binary |-
R/AgNcxASFiiJWKXqWGo5w==
type: :uuid
bsonType: "string"
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
bsonType: "object"

当使用Mongoid与Puma等分叉Web服务器或任何其他分叉以产生子进程的应用程序时,需要特别注意。

如果可能的话,我们建议在分叉之前不要在父进程中执行任何MongoDB操作,这样可以避免与分叉相关的陷阱。

driver的"使用分叉服务器"文档中给出了Mongo Ruby Driver处理分叉的详细技术说明 <https://mongodb.ac.cn/docs/ruby-driver/current/reference/create-client/#usage-with-forking-servers>。简而言之,为了避免诸如Mongo::Error::SocketErrorMongo::Error::NoServerAvailable之类的各种连接错误,必须执行以下操作

  1. 在分叉之前立即使用Mongoid.disconnect_clients断开父Ruby进程中的MongoDB客户端连接。这确保父进程和子进程不会意外地重用相同的套接字并且发生I/O冲突。请注意,Mongoid.disconnect_clients不会干扰任何正在进行的MongoDB操作,并且将在执行新操作时自动重新连接。

  2. 在分叉之后立即使用Mongoid.reconnect_clients在子Ruby进程中重新连接MongoDB客户端。这是在子进程中重新启动驱动程序的监控线程所必需的。

大多数Web服务器都提供了应用程序可以在工作进程分叉时执行动作的钩子。以下是一些常见Ruby Web服务器的配置示例。

使用 on_worker_boot 钩子来在工作者中重新连接客户端,以及使用 before_forkon_refork 钩子来关闭父进程中的客户端(请参阅Puma 文档)。

# config/puma.rb
# Runs in the Puma master process before it forks a child worker.
before_fork do
Mongoid.disconnect_clients
end
# Required when using Puma's fork_worker option. Runs in the
# child worker 0 process before it forks grandchild workers.
on_refork do
Mongoid.disconnect_clients
end
# Runs in each Puma child process after it forks from its parent.
on_worker_boot do
Mongoid.reconnect_clients
end

使用 after_fork 钩子来在工作者中重新连接客户端,以及使用 before_fork 钩子来关闭父进程中的客户端(请参阅Unicorn 文档)。

# config/unicorn.rb
before_fork do |_server, _worker|
Mongoid.disconnect_clients
end
after_fork do |_server, _worker|
Mongoid.reconnect_clients
end

使用 starting_worker_process 钩子来重新连接工作进程中的客户端(Passenger 文档)。Passenger 似乎没有在 fork 工作进程之前在父进程中调用的钩子。

if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
Mongoid.reconnect_clients if forked
end
end

mongodb ruby 驱动程序提供了一个 Rack 中间件,它可以在每个 Web 请求期间启用查询缓存。以下是在 Ruby on Rails 应用程序中启用查询缓存中间件的示例

# config/application.rb
# Add Mongo::QueryCache::Middleware at the bottom of the middleware stack
# or before other middleware that queries MongoDB.
config.middleware.use Mongo::QueryCache::Middleware

请参阅Rails on Rack 指南以获取有关在 Rails 应用程序中使用 Rack 中间件的更多信息。

MongoDB Ruby 驱动程序还为 ActiveJob 提供了查询缓存中间件。您可以在初始化器中启用它,以用于所有作业

# config/initializers/active_job.rb
# Enable Mongo driver query cache for ActiveJob
ActiveSupport.on_load(:active_job) do
include Mongo::QueryCache::Middleware::ActiveJob
end

或为特定的作业类启用

class MyJob < ActiveJob::Base
include Mongo::QueryCache::Middleware::ActiveJob
end

驱动程序的默认配置适合生产部署。在开发过程中,可以调整一些设置以提供更好的开发者体验。

  • :server_selection_timeout:如果您的MongoDB服务器本地运行且您手动启动它,请将其设置为低值(例如,1)。低服务器选择超时会导致没有服务器运行时驱动程序快速失败。

推荐的开发配置示例

development:
clients:
default:
database: mongoid
hosts:
- localhost:27017
options:
server_selection_timeout: 1

返回

兼容性