如何配置 MongoDB Java 驱动程序 MongoOptions 以供生产使用?
Posted
技术标签:
【中文标题】如何配置 MongoDB Java 驱动程序 MongoOptions 以供生产使用?【英文标题】:How to configure MongoDB Java driver MongoOptions for production use? 【发布时间】:2011-09-25 02:44:07 【问题描述】:我一直在网上搜索为 MongoDB Java 驱动程序配置 MongoOptions 的最佳实践,但除了 API 之外,我没有想出太多东西。这个搜索是在我遇到“com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db”之后开始的 连接”错误,通过增加连接/乘数,我能够解决该问题。我正在寻找链接或您在为生产配置这些选项时的最佳实践。
2.4 驱动程序的选项包括: http://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html
自动连接重试 connectionsPerHost 连接超时 最大等待时间 套接字超时 threadsAllowedToBlockForConnectionMultiplier新司机有更多选择,我也有兴趣了解这些。
【问题讨论】:
【参考方案1】:更新到 2.9:
autoConnectRetry 仅表示驱动程序将在意外断开连接后自动尝试重新连接到服务器。在生产环境中,您通常希望将此设置为 true。
connectionsPerHost 是单个 Mongo 实例(它是单例的,因此通常每个应用程序都有一个)可以建立到 mongod/mongos 进程的物理连接的数量。在撰写本文时,即使实际查询吞吐量很低,Java 驱动程序最终也会建立此数量的连接(换句话说,您将看到 mongostat 中的“conn”统计数据上升,直到每个应用服务器达到此数量)。
在大多数情况下,无需将其设置为高于 100,但此设置是“测试并查看”的内容之一。请注意,您必须确保将其设置得足够低,以便与服务器的连接总数不超过
db.serverStatus().connections.available
在生产中,我们目前有 40 个。
连接超时。顾名思义,在连接尝试中止之前,驱动程序将等待的毫秒数。将超时设置为较长的时间(15-30 秒),除非有现实的、预期的机会,否则这将妨碍成功的连接尝试。通常,如果连接尝试花费的时间超过几秒钟,您的网络基础设施就无法提供高吞吐量。
最大等待时间。线程将等待连接在连接池上可用的毫秒数,如果没有及时发生则引发异常。保持默认。
socketTimeout。标准套接字超时值。设置为 60 秒 (60000)。
threadsAllowedToBlockForConnectionMultiplier。 connectionsPerHost 的乘数,表示如果池当前已用尽,则允许等待连接变为可用的线程数。这是将导致“com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db connection”异常的设置。一旦此线程队列超过threadsAllowedToBlockForConnectionMultiplier 值,它将抛出此异常。例如,如果 connectionsPerHost 为 10,而该值为 5,则在引发上述异常之前,最多 50 个线程可以阻塞。
如果您预计可能会导致大队列的吞吐量峰值会暂时增加此值。正是出于这个原因,我们目前的价格为 1500。如果您的查询负载始终超过服务器,您应该相应地改善您的硬件/扩展情况。
读取偏好。 (已更新,2.8+) 用于确定默认读取首选项并替换“slaveOk”。通过类工厂方法之一设置 ReadPreference。 最常用设置的完整说明可在本文末尾找到
w。 (已更新,2.6+) 该值决定了写入的“安全性”。当此值为 -1 时,无论网络或数据库错误如何,写入都不会报告任何错误。 WriteConcern.NONE 是合适的预定义 WriteConcern。如果 w 为 0,则网络错误将导致写入失败,但 mongo 错误不会。这通常被称为“即发即弃”写入,并且应该在性能比一致性和持久性更重要时使用。在此模式下使用 WriteConcern.NORMAL。
如果将 w 设置为 1 或更高,则认为写入是安全的。安全写入执行写入并通过向服务器发出请求来跟踪它以确保写入成功或如果没有成功则检索错误值(换句话说,它会在您写入后发送 getLastError() 命令)。请注意,在此 getLastError() 命令完成之前,连接将被保留。作为结果和附加命令,吞吐量将显着低于 w
对于副本集,您可以为 w 使用更高的值,这会告诉 MongoDB 在返回之前将写入发送到副本集的至少“w”个成员(或更准确地说,等待您的写入复制到“ w”成员)。您还可以将 w 设置为字符串“majority”,它告诉 MongoDB 执行对大多数副本集成员的写入 (WriteConcern.MAJORITY)。通常,您应该将其设置为 1,除非您需要原始性能(-1 或 0)或复制写入(>1)。大于 1 的值对写入吞吐量有相当大的影响。
fsync。启用时强制 mongo 在每次写入后刷新到磁盘的持久性选项。我从来没有遇到过任何与写入积压相关的持久性问题,因此我们在生产中将此设置为 false(默认值)。
j *(新 2.7+)*。布尔值,当设置为 true 时强制 MongoDB 在返回之前等待成功的日志组提交。如果您启用了日记功能,则可以启用此功能以获得额外的耐用性。请参阅 http://www.mongodb.org/display/DOCS/Journaling 以了解日志记录为您带来了什么(以及您可能想要启用此标志的原因)。
阅读偏好 如果您使用副本集,ReadPreference 类允许您配置路由到哪些 mongod 实例查询。以下选项可用:
ReadPreference.primary() :所有读取仅发送到 repset 主要成员。如果您要求所有查询返回一致的(最近写入的)数据,请使用此选项。这是默认设置。
ReadPreference.primaryPreferred() :如果可能,所有读取都转到 repset 主要成员,但如果主要节点不可用,则可能会查询辅助成员。因此,如果主节点不可用,读取最终会变得一致,但前提是主节点不可用。
ReadPreference.secondary() :所有读取都转到辅助 repset 成员,而主要成员仅用于写入。仅当您可以接受最终一致的读取时才使用此选项。尽管一个 repset 可以拥有的(投票)成员数量有限制,但可以使用其他 repset 成员来提高读取性能。
ReadPreference.secondaryPreferred() :如果其中任何一个可用,则所有读取都将转到辅助 repset 成员。主要成员专门用于写入,除非所有次要成员都不可用。除了回退到主要成员进行读取之外,这与 ReadPreference.secondary() 相同。
ReadPreference.nearest() :读取到数据库客户端可用的最近的 repset 成员。仅在最终一致的读取是可接受的情况下使用。最近的成员是客户端和各个 repset 成员之间延迟最低的成员。由于忙碌的成员最终会有更高的延迟,这应该也自动平衡读取负载,尽管根据我的经验,如果成员延迟相对一致,辅助(首选)似乎做得更好。
注意:以上所有方法都具有相同方法的标签启用版本,这些版本改为返回 TaggableReadPreference 实例。副本集标签的完整描述可以在这里找到:Replica Set Tags
【讨论】:
将 socketTimeout 和 connectTimeout 保留为默认值(无限)不是很危险吗?如果连接由于某种原因挂起,您的应用程序(或至少该线程)将永远卡住。这些不应该设置得非常高吗(比如连接 30 秒,套接字 2 分钟)? 伊德里斯,非常正确。在我的帖子中,我错误地认为 MongoOptions 有我们的默认值。我们的 Mongo ORM 层分别有 15 秒和 1 分钟,在编写时我假设这些是默认值。无限超时绝对是个坏主意。感谢您的提醒,我在帖子中修复了它 “slaveOk”选项现在已被弃用,如果您希望与此等效,请执行以下操作:mongoOptions.readPreference = ReadPreference.secondaryPreferred(); 很好的答案,但您对threadsAllowedToBlockForConnectionMultiplier 的定义是错误的(关键字乘数)。根据文档:“如果connectionsPerHost为10,并且threadsAllowedToBlockForConnectionMultiplier为5,则可以阻塞的线程数的connectionsPerHost乘数,那么50个线程可以阻塞更多,并且将抛出异常” 似乎是一个非常受欢迎的答案。如果有人有兴趣我更新此内容以反映最新驱动程序的更改,请告诉我以上是关于如何配置 MongoDB Java 驱动程序 MongoOptions 以供生产使用?的主要内容,如果未能解决你的问题,请参考以下文章