设为首页 收藏本站
查看: 1336|回复: 0

[经验分享] java连接mongodb源码解读

[复制链接]

尚未签到

发表于 2018-10-25 13:53:08 | 显示全部楼层 |阅读模式
  用mongdb也大半年了,一直是业务上的逻辑实现了就ok。然而这样并不能进步……因此今天查了查java连接mongodb驱动的源码,搜到的各种信息整合一下,方便以后深入的使用。
  先贴连接数据库代码
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时进行同步。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-626422-1-1.html 上篇帖子: 【MongoDB】使用aggregate求最大值 下篇帖子: MongoDB-centos6 运维学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表