java连接mongodb源码解读-创新互联

    用mongdb也大半年了,一直是业务上的逻辑实现了就ok。然而这样并不能进步……因此今天查了查java连接mongodb驱动的源码,搜到的各种信息整合一下,方便以后深入的使用。

成都创新互联是一家专注于网站建设、做网站与策划设计,益阳网站建设哪家好?成都创新互联做网站,专注于网站建设10余年,网设计领域的专业建站公司;建站业务涵盖:益阳等地区。益阳做网站价格咨询:18982081108

    先贴连接数据库代码

 List replicaSet = new          ArrayList();          replicaSet.add(new ServerAddress("127.0.0.1", 27017));          MongoClientOptions option =          MongoClientOptions.builder().autoConnectRetry(true).connectionsPerHost(300).maxWaitTime(30000).build();          MongoConnection.init(replicaSet, option, "test");  public static synchronized void init(List replicaSet,                         MongoClientOptions option, String defaultDb){                 mongo = new MongoClient(replicaSet, option);                 mongo.setReadPreference(ReadPreference.nearest());                 setDb(mongo.getDB(defaultDb));         }

    当初一眼看过去也是头大无比,就跟大学背下来的连接mysql数据库驱动一样,只求考试默写下来不挂科。虽然也能用,但是不求甚解的态度明显是错误的!接下来分解下来一步一步看吧:

    public ServerAddress( String host , int port )         throws UnknownHostException {         if ( host == null )             host = defaultHost();         host = host.trim();         if ( host.length() == 0 )             host = defaultHost();                  int idx = host.indexOf( ":" );         if ( idx > 0 ){             if ( port != defaultPort() )                 throw new IllegalArgumentException( "can't specify port in construct and via host" );             port = Integer.parseInt( host.substring( idx + 1 ) );             host = host.substring( 0 , idx ).trim();         }         _host = host;         _port = port;         updateInetAddress();     }

    replicaSet显然是一个服务器地址数组,点进去后是对IP地址以及端口的解析。如果填写的地址是127.0.0.1:27017样式的话,冒号之后的端口必须是27017,否则就抛出异常告诉你不能自己构建主机及端口。不过既然使用了带host以及port的构造方法,地址和端口分开写就好了,何必放在一块……

boolean updateInetAddress() throws UnknownHostException {         InetSocketAddress oldAddress = _address;         _address = new InetSocketAddress( InetAddress.getByName(_host) , _port );         return !_address.equals(oldAddress);     }      volatile InetSocketAddress _address;

    至于updateInetAddress(),InetAddress是java对ip地址的封装,方便其他网络类调用,方法内部对ipv4和ipv6有各种详细的判定,不多赘述,毕竟是基础类,有时间认真学习一下提升会非常大。详细内容在这个博客里面http://my.oschina.net/fhd/blog/371997有提及。volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,要么无法编写多线程程序,要么编译器失去大量优化的机会。回到第一块,MongoClientOptions是对数据库的一些设置,用到了人民喜闻乐见的构建者模式builder:

        private String description;         private int connectionsPerHost = 100;         private int threadsAllowedToBlockForConnectionMultiplier = 5;         private int maxWaitTime = 1000 * 60 * 2;         private int connectTimeout = 1000 * 10;         private int socketTimeout = 0;         private boolean socketKeepAlive = false;         private boolean autoConnectRetry = false;         private long maxAutoConnectRetryTime = 0;         private ReadPreference readPreference = ReadPreference.primary();         private DBDecoderFactory dbDecoderFactory = DefaultDBDecoder.FACTORY;         private DBEncoderFactory dbEncoderFactory = DefaultDBEncoder.FACTORY;         private WriteConcern writeConcern = WriteConcern.ACKNOWLEDGED;         private SocketFactory socketFactory = SocketFactory.getDefault();         private boolean cursorFinalizerEnabled = true;         private boolean alwaysUseMBeans = false;

    builder给需要初始化的成员变量赋值。一个一个看吧~

  • connectionsPerHost:每个主机的连接数

  • threadsAllowedToBlockForConnectionMultiplier:线程队列数,它以上面 connectionsPerHost值相乘的结果就是线程队列大值。如果连接线程排满了队列就会抛出“Out of semaphores to get db”错误。

  • maxWaitTime:大等待连接的线程阻塞时间

  • connectTimeout:连接超时的毫秒。0是默认和无限

  • socketTimeout:socket超时。0是默认和无限

  • autoConnectRetry:这个控制是否在一个连接时,系统会自动重试

    以上解释似乎在各种需要线程池的数据库连接驱动都通用……ReadPrefrence是多个节点时读操作的设置,默认是只从主节点进行读操作,还有其他属性如只从第二节点读、从主节点读,若不可读取则再去从节点读取等等。目前还没有用到过……之前的代码设置的是从离最近的节点读取mongo.setReadPreference(ReadPreference.nearest())。然而我们的程序只有一个节点……并没有什么卵用。WriteConcern用来保障写操作的可靠性,是性能和可靠性之间的一个平衡,http://kyfxbl.iteye.com/blog/1952941这个博客中讲的比较详细。简单来说就是保障写操作确实入库了,不会因为网络状况或者服务器挂掉导致写入失败的时候得不到提醒,如果这个参数设置w:-1则得不到任何异常信息,默认w:1,最好也设置jurnal:true,写操作写入内存的同时也写入journal文件,这样如果mongod非正常down掉,重启以后就可以根据journal文件中的内容,来还原写操作。更高级别则是对多个节点的集群进行设置了,只有一个节点的话w:1&journal:true就够用了。所以第一块代码中的init方法里的synchronized到底需不需要呢……mongo既然本身就是一个线程安全的实例,mongoclient继承了mongo,是不是也意味着不需要在初始化mongoclient时进行同步。

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享文章:java连接mongodb源码解读-创新互联
本文路径:http://scyanting.com/article/dhpppg.html