如何配置MongoDB Java驱动程序MongoOptions以用于生产?


100

我一直在网上搜索有关为MongoDB Java驱动程序配置MongoOptions的最佳实践,除了API之外,我还没有提出其他建议。在我遇到“ com.mongodb.DBPortPool $ SemaphoresOut:信号量不足以获取数据库连接”错误之后,此搜索开始了,并且通过增加连接数/乘数,我能够解决该问题。我正在寻找配置这些选项的链接或您的最佳实践。

2.4驱动程序的选项包括:http : //api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • autoConnectRetry
  • connectionsPerHost
  • connectTimeout
  • maxWaitTime
  • socketTimeout
  • threadsAllowedToBlockForConnectionMultiplier

较新的驱动程序具有更多选择,我也将有兴趣了解这些。

Answers:


160

更新到2.9:

  • autoConnectRetry只是意味着驱动程序在意外断开连接后将自动尝试重新连接到服务器。在生产环境中,通常需要将此设置设置为true。

  • connectionsPerHost是单个Mongo实例(为单例,因此通常每个应用程序一个)可以建立到mongod / mongos进程的物理连接量。在编写本文时,即使实际的查询吞吐量很低,Java驱动程序也会最终建立此连接数量(按顺序,您会发现mongostat中的“ conn”统计数据会上升,直到每个应用程序服务器达到该数字为止)。

    在大多数情况下,无需将此值设置为高于100,但是此设置是“测试并查看”的事情之一。请注意,您必须确保将此值设置得足够低,以使与服务器的连接总数不超过

    db.serverStatus().connections.available

    在生产中,我们目前有40个。

  • connectTimeout。顾名思义,驱动程序将在连接尝试中止之前等待的毫秒数。除非有现实的预期机会,否则将超时设置为较长的​​时间(15-30秒),否则将以其他方式成功进行连接尝试。通常,如果连接尝试花费的时间超过几秒钟,则您的网络基础结构将无法实现高吞吐量。

  • maxWaitTime。线程将等待连接在连接池中变为可用状态的毫秒数,如果未及时发生,则会引发异常。保持默认值。

  • socketTimeout。标准套接字超时值。设置为60秒(60000)。

  • threadsAllowedToBlockForConnectionMultiplier。connectionsPerHost的乘数,它表示如果当前池已耗尽,则允许等待连接变为可用的线程数。此设置将导致“ com.mongodb.DBPortPool $ SemaphoresOut:超出信号量以获取数据库连接”异常。一旦此线程队列超过threadsAllowedToBlockForConnectionMultiplier值,它将引发此异常。例如,如果connectionsPerHost为10,并且此值为5,则在引发上述异常之前最多可以阻塞50个线程。

    如果您预计吞吐量的峰值可能会导致较大的队列,请暂时增加该值。正是由于这个原因,我们目前在1500拥有它。如果查询负载持续超过服务器,则应相应地改善硬件/扩展情况。

  • readPreference(UPDATED,2.8+)用于确定默认的读取首选项,并替换为“ slaveOk”。通过类工厂方法之一设置ReadPreference。有关最常用设置的完整说明,请参见本文末尾

  • w ^(UPDATED,2.6 +)此值确定写入的“安全性”。如果此值为-1,则无论网络或数据库错误如何,写入操作均不会报告任何错误。为此,WriteConcern.NONE是适当的预定义WriteConcern。如果w为0,则网络错误将使写入失败,但mongo错误不会。这通常被称为“开火”,当性能比一致性和耐用性更重要时,应使用该写法。在此模式下使用WriteConcern.NORMAL。

    如果将w设置为1或更高,则认为写入是安全的。安全写操作执行写操作,然后向服务器发送请求,以确保写操作成功,否则,将获取错误值(换句话说,在写操作后发送getLastError()命令)。请注意,在完成此getLastError()命令之前,将保留连接。结果是,通过附加命令,吞吐量将大大低于w <= 0时的写入。aw值恰好为1时,MongoDB确保在将写入发送到的实例上写入成功(或验证失败)。

    对于副本集,您可以使用更高的w值,告诉MongoDB在返回之前至少将写操作发送到副本集的至少“ w”个成员(或更准确地说,等待将您的写操作复制到“ w”个成员) )。您还可以将w设置为字符串“ majority”,该字符串告诉MongoDB对大多数副本集成员(WriteConcern.MAJORITY)执行写入操作。通常,除非需要原始性能(-1或0)或重复写入(> 1),否则应将其设置为1。值大于1对写吞吐量有相当大的影响。

  • fsync。持久性选项可在启用每次写入后强制mongo刷新到磁盘。我从未遇到过与写入积压相关的持久性问题,因此我们在生产中将其设置为false(默认值)。

  • j * (NEW 2.7+) *。布尔值,当设置为true时,将强制MongoDB在返回之前成功等待日志组成功提交。如果启用了日记功能,则可以启用此功能以提高耐用性。请参阅http://www.mongodb.org/display/DOCS/Journaling,以了解什么使您获得了日记功能(以及为什么要启用此标志)。

ReadPreference ReadPreference类允许您配置到使用副本集时要路由到哪些mongod实例查询。提供以下选项:

  • ReadPreference.primary():所有读取仅进入repset主要成员。如果您要求所有查询返回一致的(最近写入的)数据,请使用此选项。这是默认值。

  • ReadPreference.primaryPreferred():如果可能的话,所有读取都进入repset主要成员,但是如果主要节点不可用,则可以查询次要成员。这样,如果主数据库不可用,则读取将最终保持一致,但前提是主数据库不可用。

  • ReadPreference.secondary():所有读取都转到次要repset成员,而主要成员仅用于写入。仅当您可以接受最终一致的读取时才使用此功能。尽管repset可以拥有的(投票)成员数量有限制,但是可以使用其他repset成员来提高读取性能。

  • ReadPreference.secondaryPreferred():如果所有读取均可用,则所有读取都将转到辅助repset成员。除非所有辅助成员都不可用,否则主要成员仅用于写操作。除了回退到主要成员进行读取外,这与ReadPreference.secondary()相同。

  • ReadPreference.nearest():读取到数据库客户端可用的最近的repset成员。仅在最终一致的读取可接受时使用。最近的成员是客户端与各种repset成员之间的延迟最少的成员。由于忙碌的成员最终将具有更高的延迟,因此这也应该自动平衡读取负载,但是根据我的经验,如果成员延迟相对一致,则Secondary(首选)似乎会更好。

注意:上面所有方法都具有相同方法的启用标记的版本,这些版本将返回TaggableReadPreference实例。副本集标签的完整说明可以在这里找到:副本集标签


6
将socketTimeout和connectTimeout保留为默认值(无限)是否危险?如果连接由于某种原因挂起,则您的应用程序(或至少该线程)将永远卡住。难道不应该将它们设置得很高吗(大约30秒用于连接,2分钟用于套接字)?
Idris Mokhtarzada 2011年

伊德里斯,非常真实。在我的帖子中,我错误地认为MongoOptions具有默认值。我们的Mongo ORM层分别在15秒和1分钟时具有这些值,在撰写本文时,我假设这些是默认值。无限超时绝对不是一个好主意。感谢您的注意,我将其固定在帖子中
Remon van Vliet

现在不建议使用“ slaveOk”选项,如果您希望与此等效,请执行以下操作:mongoOptions.readPreference = ReadPreference.secondaryPreferred();
古巴创

好的答案,但是您对threadsAllowedToBlockForConnectionMultiplier的定义是错误的(关键字乘数)。根据文档:“ connectionsPerHost的乘数用于如果connectionsPerHost为10,而threadsAllowedToBlockForConnectionMultiplier为5时可以阻塞的线程数,则50个线程可以阻塞的线程数以上,并且将引发异常”
Tyler Zale

3
似乎是一个很受欢迎的答案。如果有人对我感兴趣,请进行更新以反映最新驱动程序中的更改,请告诉我
Remon van Vliet 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.