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

use*_*040 6 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"

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

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

我的代码:

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

我究竟做错了什么?

yao*_*ing 5

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

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

rs.status()
Run Code Online (Sandbox Code Playgroud)

在我的笔记本电脑中它返回这样的东西:

{
    "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
}
Run Code Online (Sandbox Code Playgroud)

这意味着有2个实例YX-ARCH:27017(主要)和YX​​-ARCH:27011(次要).

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

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

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


les*_*ese 0

What am I doing wrong? 
Run Code Online (Sandbox Code Playgroud)

我认为你不应该在连接字符串中声明仲裁器。Arbiter并不是真正的节点,它不保存任何数据,它的任务是参与replicaSet的主节点(接收写入的节点)的投票。

添加仲裁器做得很好,因为没有它,节点(和投票)是均匀的,并且无论如何您都会面临某些连接失败的情况。无论如何,你的问题与此无关。你真的需要那个吗connect=replicaset

我对 C# 了解不多,但我读到所有官方驱动程序的连接字符串都具有相同的格式,这也是 php 中的一个示例:

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

您正在测试最终一致性吗?让我知道你的想法,我没有时间检查

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