`
QING____
  • 浏览: 2231975 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Mongodb客户端原理

 
阅读更多

    JAVA客户端原理简述

    mongodb提供了官方的JAVA客户端,在上文中我们已经看到了示例。

    接下来我们简单的阐述一下它的基本原理:

    1)MongoClient参数列表中,允许指定多个mongod的addresses,注意,它们要么是同一个replica set中所有memebers列表,要么为同一个cluster的mongos列表,且不能混合使用。

    mongodb提供了2种架构模式:replica set和sharded cluster,其中replica set中多个member存储的数据一样,一个MongoClient只能允许与一个replica set通讯,它的所有members(必须为可以提供read、write操作的members)均需要传入MongoClient;对于shared cluster,通常会部署多个mongos,mongos是客户端与集群数据节点(shards节点)通讯的桥梁,因此MongoClient中可以指定多个mongos地址。

    其中addresses的顺序并不重要。

 

    2)如果指定的addresses为列表,那么MongoClient内部将构造一个MultiServerCluster实例;如果addresses为单个地址,则创建一个SingleServerCluster。

    其中MultiServerCluster内部维护一个map,Key为ServerAddress,Value为一个ClusterableServer实例;ClusterableServer接口的默认实现类为DefaultServer,它内部维护一个ConnectionPool,我们可以在创建MongoClient时指定MongoClientOptions,用于设定连接池的大小和其他一些参数(包括Socket参数、read preference、write concern等)。(参见源码:ConnectionSource,Mongo)

 

    3)对于replica set模式而言,MongoClient将同时与所有的members建立链接;其中write操作通过与primary节点建立的connection进行交互,但是对于read操作则需要调整,因为开发者可以为每个find()操作指定“read preference”(或者默认的),每个read操作都会从Server列表中根据“read perference”类型选择合适的Server(如果有多个,则最终随机选择其中一个),并将此server与操作binding,直到操作结束;如果read操作中使用了cursor,那么在cursor的整个遍历过程中,均会使用此前binding的server,不会更换server,但是因为内部ConnectionPool的机制,可能在整个Cursor遍历期间,多次IO会使用连接池中的不同的connection,不过这不会对操作带来任何问题。(参见源码:ClusterBinding,ReadPreferenceServerSelector,MongoCursor)

 

    4)对于sharded cluster而言,情况或许相对简单;因为每个mongos都可以接收read、write请求,客户端的每个操作都会从Server列表随机选择一个Server实例,然后从Server实例的连接池中获取Connection对象即可。对于Cursor问题,同3),即Cursor遍历期间,所有的IO均与一个Server通讯。

 

    5)MongoClient内置Server状态监测机制,每个Server都会初始化一个监控线程,此线程间歇性的与server地址建立链接,如果链接失败,则认为此Server,将会尝试从Server列表中移除(同时关闭其连接池中的链接);此后如果某刻,此Server再次有效,那么再次将它添加到Server列表中。

    在MongoClientOptions中可以通过“heartbeatFrequency”参数指定监测的周期(参见源码:DefaultServerMonitor,ChangeListener)

 

List<ServerAddress> replicaSet = new ArrayList<ServerAddress>();
replicaSet.add(new ServerAddress("127.0.0.1",27017));
replicaSet.add(new ServerAddress("127.0.0.1",28017));
replicaSet.add(new ServerAddress("127.0.0.1",29017));//replica set
MongoClientOptions options = MongoClientOptions.builder().writeConcern(WriteConcern.MAJORITY)
        .connectTimeout(30000)
        .connectionsPerHost(128)
        .heartbeatConnectTimeout(15000)
        .heartbeatFrequency(10000)
        .maxConnectionIdleTime(60000)
        .maxWaitTime(10000).build();
MongoClient mongoClient = new MongoClient(replicaSet,options);
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection<Document> collection = db.getCollection("user");
MongoCursor<Document> cursor = collection.find(Filters.eq("name", "zhangsan")).batchSize(32)
        .skip(200)
        .limit(32).iterator();
while (cursor.hasNext()) {
    Document item = cursor.next();
    System.out.println(item.toJson());
}
cursor.close();//must be
mongoClient.close();

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics