dongwen3093
2019-09-03 20:04
浏览 98

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

I'm not a Go guy, just need to use a plugin written in Go and I'm having some trouble between plugin and MongoDB.

The error is:

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

My configuration:

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”

The plugin snippet that performs the connection:

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
", 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

I just can't realize why the mongo driver is looking on localhost if I'm setting the address of my mongoDB server.

EDIT 1

My db has replica set configured only to use change streams.

This is my RS configuration:

{
    "_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")
    }
}

Any help solving it appreciated. Thanks

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongyi7901 2019-09-06 02:17
    已采纳

    why the mongo driver is looking on localhost if I'm setting the address of my mongoDB server.

    When mongo-go-driver's client is connecting to a MongoDB deployment, it will perform Server Discovery and Monitoring to discovers one or more servers (MongoDB being a distributed database by nature). One of the early steps is to begin monitoring the topology by invoking isMaster command on all servers. Based on the output of isMaster the client will try to contact those servers. In the case of Replica Set (your case), the client strives to connect to the primary server (from isMaster.primary).

    However, the hostname address is not a Fully Qualified Domain Name (FQDN) to be resolvable from the client's machine. The client's machine trying to connect to localhost defined as the replica set primary, thus failed to make a connection. Also, this is why you're seeing a message status where current topology: Type: Unknown but State: Connected. It failed to discover the deployment topology even before able to select a server to execute the command (ping)

    You can solve this by setting resolvable hostnames for the value of the members field in the replica set configuration. In addition, when possible, use a logical DNS hostname instead of an ip address, as this avoids configuration changes due to ip address changes.

    You can change the replica set hostnames using rs.reconfig() i.e:

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

    In your case, where there's only one replica set member it's quite straight forward. However if you're in production mode and have more than one members you can follow the steps outlined in Change Hostnames in a Replica Set where there are two options:

    Having said all the explanation above, alternatively, as your replica set deployment is only one server (development mode) you can set the connection mode to direct via ClientOptions.SetDirect(). Which specifies whether the client should connect directly to a server instead of auto-discovering other servers in the cluster (although this means you have no redundancy) i.e.:

    opts := options.ClientOptions{ ConnectTimeout: &timeoutVariable}
    opts.SetDirect(true)
    opts.ApplyURI(addr)
    
    client, err := mongo.Connect(connect.TODO(), &opts)
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题