Docs 菜单
Docs 主页
/ / /
Mongoid
/

配置

在此页面上

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

Mongoid 通常通过指定选项和客户端的 mongoid.yml 文件进行配置。最简单的配置如下:将 Mongoid 配置为与位于“localhost:27017”的 MongoDB Server 通信并使用名为“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,则在加载应用程序时,系统会自动加载存储在 Rails.env 中的当前环境的 Mongoid 配置。

您可能需要通过将以下内容添加到 application.rb,来将应用程序的 ORM 配置为 Mongoid:

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 进行配置。如果在使用或引用组件后更改配置,则更改可能不会应用于已实例化的组件。

以下带注释的示例 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.com/zh-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://www.mongodb.com/zh-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 会先使用 ERb 对其进行处理,然后将其解析为 YAML。由此能够实现的操作包括基于环境变量构建运行时配置文件的内容:

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

注意

从 ERb 输出值时,请确保这些值是有效的 YAML 并根据需要对其进行转义。

注意

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

对日志记录进行配置时,请务必记住:Mongoid 在 MongoDB Ruby 驱动程序之上提供了一个模型层,并且该驱动程序会将 CRUD 操作分派给 MongoDB 部署。因此,使用 Mongoid 的应用程序中有一些日志输出来自 Mongoid 本身,还有一些来自 Ruby 驱动程序。

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 时,默认情况下,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 的日志级别。

要以不同于 Rails 记录器的方式配置 Mongoid 或驱动程序记录器,请使用初始化程序,如下所示:

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 记录器 (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 inline 时:

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.now or Time.current` instead of ``Time.now

    • Date.current 而不是 Date.today

    请务必注意,后面的Ruby标准库方法会引用您的系统时区域(例如 UTC),而不是Time.zone的值。 由于很容易弄错这些名称相似的方法,因此我们建议使用 Rubocop 的 Rails/TimeZone cop 在您的 CI 中。

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

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

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

use_utc 只影响数据的加载方式,不影响数据的持久化。 例如,如果将TimeActiveSupport::TimeWithZone实例分配给时间字段,则始终使用所分配实例的时区信息,而不考虑use_utc设置。 或者,如果将string值分配给时间字段,则将使用string中的任何时区信息(如果存在)。 如果string不包含时区信息,将根据 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 ,它们将在驱动程序中的任何 TLS 套接字连接之前调用,并可用于修改底层OpenSSL::SSL::SSLContext套接字使用的对象。

要设置 TLS 上下文钩子,请将Proc添加到Mongo.tls_context_hooks数组。 这可以在初始化程序中完成。 以下示例添加了一个仅启用“AES 256 -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 :当连接到以snappy 开头的 MongoDB 服务器时,可以使用3 压缩。4发布,并需要 snappy 要安装的库。

  • zlib:当连接到以zlib MongoDB开头的 服务器时,可以使用3 压缩。6发布。

  • Zstandard :当连接到以zstd 开头的 MongoDB 服务器时,可以使用4 压缩。2发布,并需要 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.com/zh-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 允许该文件包含 BSON::Binary 实例,这些实例用于在模式映射中指定 keyId 以进行客户端加密,如以下示例所示:

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 与分叉 Web服务器(例如 Puma)或任何以其他方式分叉以生成子进程的应用程序一起应用时,需要特殊注意事项。

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

driver's "Usage with Forking Servers" documentation <https://www.mongodb.com/zh-cn/docs/ruby-driver/current/reference/create-client/#usage-with-forking-servers> 中提供了有关mongo Ruby驱动程序如何处理分叉的详细技术说明。 简而言之,为避免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_fork on_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 中似乎不会出现在父进程中调用的钩子。

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

MongoDB Ruby驱动程序提供了一个 Rack 中间件,该中间件在每个网络请求期间启用查询缓存。 以下示例了如何在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 Server 在本地运行,并且您会手动启动它,请将此值设置为较低的值(例如 1)。如果没有服务器正在运行,则较低的服务器选择超时会导致驱动程序快速失败。

建议的开发配置示例:

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

后退

兼容性