MongoDB Go 驱动程序何时不应该在本地主机上查找

GIJ*_*JOW 3 go mongodb

我不是 Go 人,只需要使用用 Go 编写的插件,而我在插件和 MongoDB 之间遇到了一些麻烦。

错误是:

server selection error: server selection timeout
current topology: Type: Unknown
Servers:
Addr: localhost:27017, Type: Unknown, State: Connected, Avergage RTT: 0, Last error: dial tcp 127.0.0.1:27017: connect: connection refused
exit status 1
Run Code Online (Sandbox Code Playgroud)

我的配置:

time=“2019-09-03T16:29:35Z” level=debug msg=“Host: ip-XXX-XX-XX-XXX.sa-east-1.compute.internal”
time=“2019-09-03T16:29:35Z” level=debug msg=“Port: 27017”
time=“2019-09-03T16:29:35Z” level=debug msg=“Username: user”
time=“2019-09-03T16:29:35Z” level=debug msg=“Password: user123*”
time=“2019-09-03T16:29:35Z” level=debug msg=“DBName: dbBackend”
Run Code Online (Sandbox Code Playgroud)

执行连接的插件片段:

addr := fmt.Sprintf("mongodb://%s:%s", m.Host, m.Port)

to := 60 * time.Second
opts := options.ClientOptions{
    ConnectTimeout: &to,
}

opts.ApplyURI(addr)



if m.Username != "" && m.Password != "" {
    opts.Auth = &options.Credential{
        AuthSource:  m.DBName,
        Username:    m.Username,
        Password:    m.Password,
        PasswordSet: true,
    }
}

client, err := mongo.Connect(context.TODO(), &opts)

if err != nil {
    return m, errors.Errorf("couldn't start mongo backend. error: %s\n", err)
}

err1 := client.Ping(context.TODO(), nil)

if err1 != nil {    
    log.Fatal(err1) // error happens here
} 

log.Debugf("MONGO CONNECTED")

m.Conn = client

return m, nil
Run Code Online (Sandbox Code Playgroud)

如果我正在设置 mongoDB 服务器的地址,我就是不明白为什么 mongo 驱动程序会在 localhost 上查找。

编辑 1

我的数据库已将副本集配置为仅使用更改流。

这是我的 RS 配置:

{
    "_id" : "rs0",
    "version" : 69559,
    "protocolVersion" : 1,
    "writeConcernMajorityJournalDefault" : true,
    "members" : [
        {
            "_id" : 0,
            "host" : "localhost:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {

            },
            "slaveDelay" : 0,
            "votes" : 1
        }
    ],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "catchUpTimeoutMillis" : -1,
        "catchUpTakeoverDelayMillis" : 30000,
        "getLastErrorModes" : {

        },
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("5cf684c3c0db3f53727d1bb4")
    }
}
Run Code Online (Sandbox Code Playgroud)

任何帮助解决它表示赞赏。谢谢

Wan*_*iar 5

如果我正在设置 mongoDB 服务器的地址,为什么 mongo 驱动程序会在 localhost 上查找。

mongo-go-driver的客户端连接到 MongoDB 部署时,它将执行服务器发现和监控以发现一个或多个服务器(MongoDB 本质上是一个分布式数据库)。早期步骤之一是通过在所有服务器上调用isMaster 命令开始监视拓扑。根据isMaster 的输出,客户端将尝试联系这些服务器。在副本集的情况下(你的情况),客户端努力连接到主服务器(从isMaster.primary)。

但是,主机名地址不是可从客户端计算机解析的完全限定域名 (FQDN)。尝试连接的客户端机器localhost定义为副本集主要,因此无法建立连接。此外,这就是为什么您会看到消息状态,current topology: Type: Unknown但是State: Connected。即使在能够选择服务器来执行命令之前,它也未能发现部署拓扑 ( ping)

您可以通过为副本集配置中的 members 字段的值设置可解析的主机名来解决此问题。此外,如果可能,请使用逻辑 DNS 主机名而不是 ip 地址,因为这可以避免由于 ip 地址更改而导致的配置更改。

您可以使用rs.reconfig()更改副本集主机名,即:

cfg = rs.conf()
cfg.members[1].host = "<RESOLVABLE HOSTNAME>:<PORT NUMBER>"
rs.reconfig(cfg)
Run Code Online (Sandbox Code Playgroud)

在您的情况下,只有一个副本集成员,这是非常简单的。但是,如果您处于生产模式并且拥有多个成员,则可以按照更改副本集中的主机名中列出的步骤进行操作,其中有两个选项:

说了以上所有解释,或者,由于您的副本集部署只是一台服务器(开发模式),您可以direct通过ClientOptions.SetDirect()设置连接模式。它指定客户端是否应该直接连接到服务器而不是自动发现集群中的其他服务器(尽管这意味着您没有冗余)即:

opts := options.ClientOptions{ ConnectTimeout: &timeoutVariable}
opts.SetDirect(true)
opts.ApplyURI(addr)

client, err := mongo.Connect(connect.TODO(), &opts)
Run Code Online (Sandbox Code Playgroud)