无法连接到与读取首选项Primary匹配的副本集的成员

时间:2014-01-25 12:37:29

标签: c# mongodb mongodb-.net-driver

我有3个mongodb节点:主要,次要和仲裁(版本2.4.9)

我有mongodb C#驱动程序1.8.3 我使用以下连接字符串:

  

连接字符串“mongodb:// mongo2,mongo1,mongo3 /?connect = replicaset& replicaset = myrs& readPreference = SecondaryPreferred”

当录制半个案例时,驱动程序会抛出异常:

  

无法连接到与读取首选项主

匹配的副本集的成员

我的代码:

        var client = new MongoClient(connectionString);
        var server = client.GetServer();
        var database = server.GetDatabase(dbName);
        var collection = database.GetCollection<T>(collectionName);
        collection.Insert(newDoc);

我做错了什么?

4 个答案:

答案 0 :(得分:5)

我怀疑是因为你提供了错误的主机名。

这是你应该知道的一件事,可用的mongo实例列表不是来自你的连接字符串,它来自第一个可用的mongo实例的返回结果。例如,当驱动程序与实例mongo1进行通信时,它会获取可用实例的列表,您可以使用以下命令获取这些实例:

rs.status()

在我的笔记本电脑中它会返回如下内容:

{
    "set" : "rs0",
    "date" : ISODate("2014-01-27T06:43:11Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "YX-ARCH:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 15894,
            "optime" : Timestamp(1390804960, 1),
            "optimeDate" : ISODate("2014-01-27T06:42:40Z"),
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "YX-ARCH:27011",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 31,
            "optime" : Timestamp(1390804960, 1),
            "optimeDate" : ISODate("2014-01-27T06:42:40Z"),
            "lastHeartbeat" : ISODate("2014-01-27T06:43:10Z"),
            "lastHeartbeatRecv" : ISODate("2014-01-27T06:43:10Z"),
            "pingMs" : 0,
            "syncingTo" : "YX-ARCH:27017"
        }
    ],
    "ok" : 1
}

这意味着有2个实例YX-ARCH:27017(主要)&amp; YX-ARCH:27011(中学)。

现在重点是,这些主机名必须可以在IIS服务器中解析,因为您的驱动程序将使用这些地址连接到mongo实例。

因此,如果主机名解析为Internet IP,而您的mongo服务仅适用于Intranet,则您永远无法连接到它。你得到上面的错误。

还有一件事,不建议每次都创建一个新的MongoClient实例。从文档中你可以知道它是线程安全的类。并将MongoClient添加到驱动程序中以管理副本集内容。所以在我看来你应该把它保留为单个实例对象。因为每次创建新实例时,它都会尝试从一个实例获取副本集设置,这对效率来说并不是一件好事。

答案 1 :(得分:0)

What am I doing wrong? 

我认为你不应该在连接字符串中声明仲裁者。 Arbiter实际上并不是一个它不保存任何数据的节点,它的任务是参与复制集的主节点(接受写入的人)的投票。

你最好添加仲裁器,因为没有它,节点(和投票)是偶数,你无论如何都会面临一些连接失败的情况。无论如何,你的问题与此无关。你真的需要connect=replicaset吗?

我对C#知之甚少,但我read连接字符串的格式与所有官方驱动程序相同,这也是php中的一个例子:

    $m = new MongoClient("mongodb://mongo1:27017,mongo2:27018/?replicaSet=myrs&readPreference=secondary");

您是否在测试最终的一致性?让我知道你对它的看法,我没时间检查它

不知道它是否区分大小写但请注意大写字母replicaSet=myrs

答案 2 :(得分:0)

我知道帖子已经过时了,但我上周遇到了这个问题,我能够解决问题。

您必须检查几件事:

  1. 如果 connectionstrings.config 中托管了 mongodb 的连接,则<Requirements> <Sets> <Set Name="WordApi" MinVersion="1.2" /> <Set Name="File" MinVersion="1.1" /> <Set Name="Settings" MinVersion="1.1" /> <Set Name="CustomXmlParts" MinVersion="1.1" /> </Sets> <Methods> <Method Name="Document.getFilePropertiesAsync" /> </Methods> </Requirements> 应为&,否则您将获得&# 39;实体问题&#39;。
  2. 不要忘记添加mongodb端口&amp;
  3. 使用27017而不是primaryPreffered - 这是因为您希望应用程序在正常情况下从主数据库读取,但是当主数据库不可用时允许从辅助服务器进行过时读取。这为故障转移期间的应用程序提供了“只读模式”。使用secondaryPreferred是反指示。从mongodb官方文档here了解更多信息。

  4. 显而易见的一个是检查副本集是否相互连接,这意味着它是仲裁成员,因此您会遇到该问题。我想打赌,如果你只把mongo1和删除其他副本设置参数,它将完美地工作。

  5. 正如 yaoxing 提到的那样,如果你使用mongodb主机/名称确保它们是正确的,进一步的测试是使用MongoDB IP地址而不是主机/名称,这仍然可以根据我的工作测试。
  6. Mongodb参数区分大小写,因此最好确保使用 lese 所述的secondaryPreferred而不是replicaSet
  7. 如果您有仲裁成员,则不必将其包含在您的连接中。
  8. 此外,您可以检查此MongoDB配置article。它还包括加密,以防万一你想要它,但总的来说,如果所有的点都得到解决,你不应该有这个问题。

答案 3 :(得分:0)

对我来说,很少有mongo服务器崩溃,因此我看到了错误。请检查您的mongo db服务器连接性