【问题标题】:Docker and mongo-go-driver "server selection error"Docker 和 mongo-go-driver “服务器选择错误”
【发布时间】:2019-10-17 00:15:24
【问题描述】:

我使用 Docker 创建了一个 MongoDB 副本集,我可以使用控制台或 Robo3T 访问并运行任何查询。

容器如下所示:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
efe6ae03323d        mongo               "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:30001->27017/tcp   mongo1
57d2701c8a43        mongo               "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:30002->27017/tcp   mongo2
7553966b9ff5        mongo               "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:30003->27017/tcp   mongo3

当我尝试使用mongo-go-driver ping 时出现错误(我尝试使用版本 1.0.0 和 1.0.2)

// Create MongoDB client    
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:30001"))
if err != nil {
    t.Fatalf("Exit error: %v", err)
}

ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
err = client.Connect(ctx)
if err != nil {
    t.Fatalf("Exit error: %v", err)
}

ctx, cancel = context.WithTimeout(context.Background(), time.Minute)
defer cancel()

// Ping
err = client.Ping(ctx, readpref.Primary())
if err != nil {
    t.Fatalf("Exit error Ping: %v", err)
}

Ping 调用引发的错误如下:

Exit error Ping: server selection error: server selection timeout
        current topology: Type: ReplicaSetNoPrimary
        Servers:
        Addr: mongo2:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo2: no such host
        Addr: mongo3:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo3: no such host
        Addr: mongo1:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo1: no such host

感谢大家的支持!

【问题讨论】:

  • 你在使用 docker-compose 文件吗?
  • @GeorgeOikonomou 不,我设置了运行docker 命令的容器

标签: mongodb docker go mongodb-query


【解决方案1】:

这是由于来自 Docker 主机的未解决的hostname。在 Docker 中,实例 mongo1mongo2mongo3 可以通过这些名称访问。但是,这些名称无法从 Docker 主机访问。这句话很明显:

Addr: mongo2:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo2: no such host

MongoDB 驱动程序将从给定的副本集成员中尝试server discovery;它将找到副本集中的所有其他节点(通过rs.conf)。这里的问题是副本集设置为名称mongo<N>,驱动程序(在 Docker 主机中运行)将无法解析这些名称。您可以通过尝试从 Docker 主机 ping mongo1 来确认这一点。

您可以尝试从另一个与副本集共享相同 Docker 网络的 Docker 实例运行应用程序。或者,修改 Docker 网络以允许可解析的主机名。

更新:

关于您对为什么使用mongo shell 或PyMongo 有效的评论。

这是由于连接方式不同造成的。当指定单个节点时,即 shell 或 PyMongo 中的 mongodb://node1:27017,不会进行服务器发现。相反,它将尝试连接到该单个节点(不作为副本集的一部分)。问题是您需要连接到副本集的主节点才能写入(您必须知道是哪一个)。如果您想作为副本集连接,则必须定义副本集名称。

mongo-go-driver 相比,默认情况下它会执行服务器发现并尝试作为副本集进行连接。如果您想作为单个节点进行连接,则需要在连接 URI 中指定 connect=direct。另见Example Connect Direct

【讨论】:

  • 好的,对!但我不明白为什么,例如,使用 pymongo 我可以连接和测试副本。
  • 使用 pymongo 可以正常工作,因为当您只提供一个节点时,Pymongo 不会进行服务器发现。它只是连接到那个节点(而不是作为副本集)。如果你想做同样的事情,只连接一个节点而不是使用 mongo-go-driver 的副本集,你必须指定“connect=direct”
  • 好的,它正在工作!我会考虑什么对我的情况更好,谢谢您的支持
  • @WanBachtiar 如果我将 connect=direct 与mongodb://primary:27018,secondary:27019/clickshield?replicaSet=rs0&connect=direct 这样的连接字符串一起使用会发生什么?有不好的副作用吗?
  • @john 指定该 URI 的意图和目的是什么?请随意提出一个新问题。
猜你喜欢
  • 2020-07-03
  • 2023-01-07
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 2020-02-08
  • 2019-07-13
  • 2019-08-05
相关资源
最近更新 更多