[druid 源碼解析] 7 HighAvailableDataSource 簡(jiǎn)單使用

關(guān)于 HighAvailableDataSource 的介紹,我們可以看一下官方文檔相關(guān)的介紹,官方文檔主要介紹如下幾個(gè)作用:

  1. 節(jié)點(diǎn)路由 - 根據(jù)節(jié)點(diǎn)名稱指定路由,隨機(jī)路由,粘性隨機(jī)路由
  2. 節(jié)點(diǎn)配置 - 純手工配置節(jié)點(diǎn),根據(jù)配置文件生成節(jié)點(diǎn),根據(jù)ZooKeeper信息生成節(jié)點(diǎn)
  3. 節(jié)點(diǎn)健康檢查 - 基于ValidConnectionChecker的節(jié)點(diǎn)檢查機(jī)制扔涧,檢查間隔時(shí)間可根據(jù)運(yùn)行情況動(dòng)態(tài)調(diào)整。
    我們接下來(lái)來(lái)測(cè)試一下這幾部分的內(nèi)容届谈。

路由節(jié)點(diǎn)

首先我們來(lái)測(cè)試路由節(jié)點(diǎn)功能枯夜,路由節(jié)點(diǎn)需要我們配置多個(gè)數(shù)據(jù)源,然后注入到 HighAvailableDataSource 中艰山,并最終生成  Datasource 湖雹。我們先來(lái)看一下配置類的信息 :

@org.springframework.context.annotation.Configuration
public class Configuration {

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    @Qualifier("dataSource1")
    DataSource dataSource1;

    @Autowired
    @Qualifier("dataSource2")
    DataSource dataSource2;


    @Bean(initMethod = "init")
    public DataSource dataSource1() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/information_schema?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
        return druidDataSource;
    }

    @Bean(initMethod = "init")
    public DataSource dataSource2() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/information_schema?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
        return druidDataSource;
    }

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public DataSource dataSource() {
        HighAvailableDataSource druidDataSource = new HighAvailableDataSource();
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("dataSources1", dataSource1);
        dataSourceMap.put("default", dataSource1);
        dataSourceMap.put("dataSources2", dataSource2);
        druidDataSource.setDataSourceMap(dataSourceMap);
        druidDataSource.setSelector("byName");
        return druidDataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setMapperLocations(applicationContext.getResources("classpath:mapper/*.xml"));
        return sqlSessionFactory;
    }
}

如圖,我們首先要生成了兩個(gè) Datasource 曙搬, 最后注入到 HighAvailableDataSource 摔吏,有些同學(xué)會(huì)注意到,這里不是使用 ObjectProvider 來(lái)獲取多個(gè)數(shù)據(jù)源數(shù)據(jù)源纵装,也是經(jīng)過(guò)一位大佬的提醒征讲,我才意識(shí)到這個(gè)問(wèn)題,構(gòu)造注入的方式是沒(méi)法解決循環(huán)依賴的橡娄,而這里恰好有循環(huán)依賴的問(wèn)題诗箍。

循環(huán)依賴報(bào)錯(cuò)

回到正題,我們最后初始化完成后挽唉,日志會(huì)打印這兩個(gè)數(shù)據(jù)源初始化完成滤祖。接著我們就可以像使用同個(gè)數(shù)據(jù)源來(lái)使用他了。
初始化

根據(jù)ZooKeeper生成節(jié)點(diǎn)集合

在開始Demo前瓶籽,我們需要先在 zookeeper 注冊(cè)數(shù)據(jù)源相關(guān)的節(jié)點(diǎn)匠童,如下:

ZookeeperNodeRegister register = new ZookeeperNodeRegister();
        register.setZkConnectString("127.0.0.1:2181");
        register.setPath("/ha-druid-datasources");
        register.init();

        List<ZookeeperNodeInfo> payload = new ArrayList<ZookeeperNodeInfo>();
        ZookeeperNodeInfo node = new ZookeeperNodeInfo();
        node.setPrefix("ha");
        node.setHost("127.0.0.1");
        node.setPort(3306);
        node.setDatabase("information_schema");
        node.setUsername("root");
        node.setPassword("root");
        payload.add(node);
        register.register("datasource1", payload);


        ZookeeperNodeRegister register2 = new ZookeeperNodeRegister();
        register2.setZkConnectString("127.0.0.1:2181");
        register2.setPath("/ha-druid-datasources");
        register2.init();

        List<ZookeeperNodeInfo> payload2 = new ArrayList<ZookeeperNodeInfo>();
        ZookeeperNodeInfo node2 = new ZookeeperNodeInfo();
        node2.setPrefix("ha");
        node2.setHost("127.0.0.1");
        node2.setPort(3307);
        node2.setDatabase("information_schema");
        node2.setUsername("root");
        node2.setPassword("root");
        payload2.add(node2);
        register2.register("datasource2", payload2);
        Thread.sleep(1000 * 60 * 60);

我們注冊(cè)了兩個(gè)數(shù)據(jù)源信息,分別是本地的 3306 和 3307 端口塑顺,然后停止該線程一個(gè)小時(shí)汤求,我們需要注意的是假如線程掛了,那么注冊(cè)的臨時(shí)幾點(diǎn)也將消失,所以需要 sleep 首昔,接下來(lái)我們到zk 上看一下注冊(cè)節(jié)點(diǎn)的信息如下:


zk

zk 準(zhǔn)備好后我們使用對(duì)數(shù)據(jù)源進(jìn)行配置赋朦,如下:

@Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setMapperLocations(applicationContext.getResources("classpath:mapper/*.xml"));
        return sqlSessionFactory;
    }

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public DataSource dataSource(ZookeeperNodeListener zkNodeListener) {
        HighAvailableDataSource druidDataSource = new HighAvailableDataSource();
        druidDataSource.setNodeListener(zkNodeListener);
        druidDataSource.setSelector("random");
        druidDataSource.setPoolPurgeIntervalSeconds(60);
        druidDataSource.setAllowEmptyPoolWhenUpdate(false);
        return druidDataSource;
    }

    @Bean
    public ZookeeperNodeListener zkNodeListener() {
        ZookeeperNodeListener zookeeperNodeListener = new ZookeeperNodeListener();
        zookeeperNodeListener.setZkConnectString("localhost:2181");
        zookeeperNodeListener.setPath("/ha-druid-datasources");
        zookeeperNodeListener.setUrlTemplate("jdbc:mysql://${host}:${port}/${database}?useUnicode=true");
        zookeeperNodeListener.setPrefix("ha");
        return zookeeperNodeListener;
    }

與之前使用兩個(gè) datasource 不同绎签,這里是直接注入了一個(gè)zookeeperNodeListener,即不使用默認(rèn)的隨機(jī) selector 濒募。接著我們啟動(dòng)服務(wù)巧骚,可以看到以下信息赊颠,代表我們數(shù)據(jù)源初始化成功。

log

我們可以先測(cè)試一下當(dāng)前數(shù)據(jù)是否可用劈彪,然后試著斷開剛才 sleep 的線程竣蹦,可以看到日志打印出如下信息,刪除節(jié)點(diǎn)成功:
log

還有關(guān)閉數(shù)據(jù)源的日志如下:
log

我們可以看到這里只刪除了 datasource1 , 我們重新進(jìn)行測(cè)試沧奴,還是能正常獲取到 datasource2 痘括。這里主要是我們?cè)O(shè)置了如下屬性,所以并不會(huì)刪除所有的節(jié)點(diǎn):

druidDataSource.setAllowEmptyPoolWhenUpdate(false);

還有最后一個(gè)部分就是 節(jié)點(diǎn)健康檢查 滔吠,這部分主要是一些配置相關(guān)的纲菌,就不進(jìn)行細(xì)講了,有興趣的同學(xué)可以自己配置試一下疮绷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翰舌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子冬骚,更是在濱河造成了極大的恐慌椅贱,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件只冻,死亡現(xiàn)場(chǎng)離奇詭異庇麦,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)喜德,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門山橄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人住诸,你說(shuō)我怎么就攤上這事驾胆。” “怎么了贱呐?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵丧诺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我奄薇,道長(zhǎng)驳阎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮呵晚,結(jié)果婚禮上蜘腌,老公的妹妹穿的比我還像新娘。我一直安慰自己饵隙,他們只是感情好撮珠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著金矛,像睡著了一般芯急。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驶俊,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天娶耍,我揣著相機(jī)與錄音,去河邊找鬼饼酿。 笑死榕酒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的故俐。 我是一名探鬼主播想鹰,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼购披!你這毒婦竟也來(lái)了杖挣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刚陡,失蹤者是張志新(化名)和其女友劉穎惩妇,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筐乳,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歌殃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蝙云。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氓皱。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖勃刨,靈堂內(nèi)的尸體忽然破棺而出波材,到底是詐尸還是另有隱情,我是刑警寧澤身隐,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布廷区,位于F島的核電站,受9級(jí)特大地震影響贾铝,放射性物質(zhì)發(fā)生泄漏隙轻。R本人自食惡果不足惜埠帕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玖绿。 院中可真熱鬧敛瓷,春花似錦、人聲如沸斑匪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秤标。三九已至绝淡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苍姜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工悬包, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衙猪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓布近,卻偏偏與公主長(zhǎng)得像垫释,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撑瞧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容