原则 ODM / MongoDB 不重试查询


Doctrine ODM / MongoDB not retrying queries?

我正在使用Doctrine ODM连接到MongoDB。我有一个三节点副本集:两个完整副本和一个仲裁节点。复制只是为了更高的可用性,我不寻求跨节点分布读取。我的应用程序每隔一段时间就会记录MongoCursorException,并显示消息not master and slaveok=false。我没有看到任何证据表明mongodb日志中发生了故障转移事件并且主日志没有更改。更正:故障转移确实发生了,但not master and slaveok=false异常经常出现,甚至在成功选择新的主节点 6 小时后出现。

怎么办?我看到我们的 doctrine-mongodb 版本包括(实验性?)重试功能,但我没有看到一种简单的方法来启用它。

不确定这是否重要,但这是一个Symfony2(v2.0)应用程序。

https://groups.google.com/d/topic/mongodb-user/6p710Rdycpg/discussion 意味着我们需要重试(强调我的):

必须编写应用程序以重新连接/重试,因为存在 任何数量的瞬态(网络)错误,可能会出现很像 正常操作期间的滚动升级过程。

Mongo PHP 扩展文档似乎考虑到了这一点:

如果第一次尝试由于某些原因失败,驱动程序将自动重试"纯"查询(不是命令)几次。这是为了在副本集故障转移期间减少异常(尽管您可能仍然需要处理一些异常)并掩盖暂时性网络问题。

我以为doctrine-mongodb只是用PHP扩展来实际与mongod交谈。所以我有点困惑是否应该担心重试配置。

我想我解决了部分问题:我按照克里斯蒂娜·乔多罗的建议从连接字符串中删除了仲裁器。我不再看到任何带有消息not master and slaveok=false MongoCursorException。我可能打 https://jira.mongodb.org/browse/PHP-392 了。

但是,在故障转移期间,我仍然收到一些消息couldn't determine master MongoCursorException。例如,我刚刚进行了故障转移;根据 Mongod 日志,几秒钟后选出了新的初选,但 Web 应用程序甚至在 5 分钟后就抛出了该异常。

我假设你正在使用与DoctrineMongoDBBundle上的2.0分支相对应的标签之一(目前最高为2.2.1)。Symfony 2.1+兼容性在捆绑包的标签版本3+中。

配置类在文档管理器级别公开retry_queryretry_connect选项,这些选项默认为零。在 YML 中,配置如下所示:

doctrine_mongodb:
    # Other proxy, hydrator and connection configuration options
    default_document_manager: dm1
    document_managers:
        dm1:
            retry_query: 1
            retry_connect: 1
            # Other mapping, metadata and DM options follow

我意识到捆绑包文档中没有提到这一点,所以我只是在此提交中添加了一个部分。

您是否将 replicaSet 选项配置为指向在 MongoDB 中配置的指定副本集?

Symfony DoctrineMongoDBBundle Docs

查看底部的完整配置。据我所知,您需要命名服务器配置行中的所有服务器,并在选项部分中命名副本集。该页面上的文档没有说得很清楚。

查看代码。看起来应该通过设置来配置重试系统。

retryConnect
retryQuery

与数据库名称处于同一级别。

这是我的Zend框架配置的一个例子,它基本上做了同样的事情。

; Database details
resources.odm.configuration.defaultDB = "test"
resources.odm.connection.options.replicaSet = "test-replica-set"
resources.odm.connection.server = "mongodb://rs1a.testing.com:27017,rs1b.testing.com:27017,rs1c.testing.com:27017"
resources.odm.configuration.retryConnect = 3
resources.odm.configuration.retryQuery = 3

当我没有配置副本集时,我遇到了类似的错误。