The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Vegetable

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

  •  
  •   Vegetable · May 21, 2020 · 2252 views
    This topic created in 2291 days ago, the information mentioned may be changed or developed.

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

    情景

    本地使用 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 不行

    有可能是哪里的问题?

    Supplement 1  ·  May 21, 2020
    找到问题了,需要显式指定 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 replies    2020-05-21 16:19:42 +08:00
    defunct9
        1
    defunct9  
       May 21, 2020
    没道理
    Vegetable
        2
    Vegetable  
    OP
       May 21, 2020
    @defunct9 uri 加一句?connect=direct 就能正确连接了,浪费了生命中的一个小时
    dafsic
        3
    dafsic  
       May 21, 2020
    config.Mongo.URI 这个是一个集群的地址,但端口映射只映射了集群中一个主机的地址,是不是这个原因?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3084 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 62ms · UTC 03:15 · PVG 11:15 · LAX 20:15 · JFK 23:15
    ♥ Do have faith in what you're doing.