V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Vegetable
V2EX  ›  Go 编程语言

遇到了一个关于连接 Mongodb 的怪事,帮判断一下

  •  
  •   Vegetable · 2020-05-21 15:25:31 +08:00 · 1749 次点击
    这是一个创建于 1643 天前的主题,其中的信息可能已经有所发展或是发生改变。

    可能触及到我知识的盲区了

    情景

    本地使用 ssh -L 127.0.0.1:27017:{aliyun.mongodburi}:3717 {user}@{ip} 建立 ssh 通道,将本地的 27017 端口映射到服务器,访问阿里云的 mongodb (无验证),然后在本地运行一些脚本。

    映射应该没问题

    $ curl 127.0.0.1:27017
    It looks like you are trying to access MongoDB over HTTP on the native driver port.
    

    在用 pymongo 时一切正常。

    client = MongoClient() # pretty well
    

    今天用了 https://github.com/mongodb/mongo-go-driver,发现在本地无法连接,一直超时。

    func initMongoConnection() {
    	ctx, _ := context.WithTimeout(context.Background(), time.Second*10)
    	log.Println(config.Mongo.URI) // "mongodb://localhost:27017"
    	client, err := mongo.Connect(ctx, options.Client().ApplyURI(config.Mongo.URI))
    	if err != nil {
    		panic(err)
    	}
    	err = client.Ping(ctx, readpref.Primary())
    	if err != nil {
    		panic(err) //panic: context deadline exceeded
    	}
    }
    
    

    编译之后拿到服务器上去跑又没问题(基本可以定位问题出现在通道上)。本地不走通道访问另一台局域网的 MongoDB,也没问题。
    本地到 ssh 服务器的连接速度问题应该可以排除 总结就是:

    • python + pymongo + ssh 没问题(速度很快,应该可以排除网络问题造成超时)
    • golang + mongo-go-driver 没问题
    • goalng + mongo-go-driver + ssh 不行

    有可能是哪里的问题?

    第 1 条附言  ·  2020-05-21 16:01:27 +08:00
    找到问题了,需要显式指定 SetDirect

    ```Go
    client, err := mongo.Connect(ctx, options.Client().ApplyURI(config.Mongo.URI).SetDirect(true))
    ```
    造成这个的原因我也搞不太清楚。

    ```Golang
    // SetDirect specifies whether or not a direct connect should be made. To use this option, a URI with a single host must
    // be specified through ApplyURI. If set to true, the driver will only connect to the host provided in the URI and will
    // not discover other hosts in the cluster. This can also be set through the "connect" URI option with the following
    // values:
    //
    // 1. "connect=direct" for direct connections
    //
    // 2. "connect=automatic" for automatic discovery.
    //
    // The default is false ("automatic" in the connection string).
    func (c *ClientOptions) SetDirect(b bool) *ClientOptions {
    c.Direct = &b
    return c
    }
    ```

    可能是因为驱动在默认情况下是自动寻找 Mongodb,又因为通过了通道的原因,驱动无法判断服务器的真实地址,尝试在跳板服务器本身寻找 Mongodb 服务,造成连接失败。指定了直接连接之后就没这问题了。
    3 条回复    2020-05-21 16:19:42 +08:00
    defunct9
        1
    defunct9  
       2020-05-21 15:29:56 +08:00
    没道理
    Vegetable
        2
    Vegetable  
    OP
       2020-05-21 16:02:14 +08:00
    @defunct9 uri 加一句?connect=direct 就能正确连接了,浪费了生命中的一个小时
    dafsic
        3
    dafsic  
       2020-05-21 16:19:42 +08:00
    config.Mongo.URI 这个是一个集群的地址,但端口映射只映射了集群中一个主机的地址,是不是这个原因?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1020 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:21 · PVG 06:21 · LAX 14:21 · JFK 17:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.