四笙蒙、MyCat 初始化

MyCat 初始化主要負(fù)責(zé)啟動 MycatServer 實(shí)例,啟動 MycatServer 實(shí)例的過程中聚唐,核心工作是讀取并解析 Mycat 配置文件(schema.xml丐重、rule.xml 和 server.xml)。MycatServer 使用”餓漢模式“初始化一個(gè)單例

public class MycatServer {
    private static final MycatServer INSTANCE = new MycatServer();
    
    public static final MycatServer getInstance() {
        return INSTANCE;
    }
    
    private MycatServer() {
        // 讀取文件配置
        this.config = new MycatConfig();
        ...
    }
}

讀取并解析 MyCat 配置文件的具體實(shí)現(xiàn)交由 MycatConfig杆查。MycatConfig 內(nèi)部使用 ConfigInitializer 解析全局配置扮惦。ConfigInitializer 主要處理一下幾件事情:

  1. 讀取 schema.xml、rule.xml 和 server.xml 文件并將解析到的配置類賦給 ConfigInitializer 的變量中
  2. 解析 DataHost 和對應(yīng)的 DataNode亲桦,創(chuàng)建物理數(shù)據(jù)庫連接池(PhysicalDBPool)和物理數(shù)據(jù)庫節(jié)點(diǎn)(PhysicalDBNode)
  3. 權(quán)限管理設(shè)置
  4. 加載全局序列處理器配置
  5. 配置文件自檢

在此我重點(diǎn)敘述 1 和 2

4.1 配置文件讀取

// 讀取 rule.xml和schema.xml
SchemaLoader schemaLoader = new XMLSchemaLoader();
// 讀取 server.xml
XMLConfigLoader configLoader = new XMLConfigLoader(schemaLoader);

4.2 創(chuàng)建物理數(shù)據(jù)庫連接池(PhysicalDBPool)

initDataHosts 為每一個(gè) <dataHost> 節(jié)點(diǎn)創(chuàng)建一個(gè)數(shù)據(jù)庫連接池崖蜜,創(chuàng)建完成后返回 Map<String, PhysicalDBPool> physicalDBPoolMap,其中 key 為 <dataHost> 節(jié)點(diǎn)的 name 屬性值客峭,value 為 <dataHost> 節(jié)點(diǎn)對應(yīng)的數(shù)據(jù)庫連接池

private Map<String, PhysicalDBPool> initDataHosts(ConfigLoader configLoader) {
    Map<String, DataHostConfig> dataHostConfigMap = configLoader.getDataHosts();
    Map<String, PhysicalDBPool> physicalDBPoolMap = new HashMap<>(dataHostConfigMap.size());
    for (DataHostConfig dataHostConfig : dataHostConfigMap.values()) {
        // 為每個(gè) dataHost 節(jié)點(diǎn)建立一個(gè) PhysicalDBPool
        PhysicalDBPool pool = getPhysicalDBPool(dataHostConfig, configLoader);
        physicalDBPoolMap.put(pool.getHostName(), pool);
    }
    return physicalDBPoolMap;
}

io.mycat.config.ConfigInitializer#getPhysicalDBPool 方法為每個(gè) <dataHost> 節(jié)點(diǎn)建立一個(gè) PhysicalDBPool豫领,主要工作如下:

  1. 為每一個(gè) <dataHost> 節(jié)點(diǎn)的 < writeHost> 節(jié)點(diǎn)創(chuàng)建一個(gè) PhysicalDatasource
  2. 為每一個(gè) <dataHost> 節(jié)點(diǎn)的 <readHost> 節(jié)點(diǎn)創(chuàng)建一個(gè) PhysicalDatasource
  3. 初始化 PhysicalDBPool 并返回
private PhysicalDBPool getPhysicalDBPool(DataHostConfig dataHostConfig, ConfigLoader configLoader) {
    // dataHost 節(jié)點(diǎn)名
    String name = dataHostConfig.getName();
    // 數(shù)據(jù)庫類型,我們這里只討論MySQL
    String dbType = dataHostConfig.getDbType();
    // 連接數(shù)據(jù)庫驅(qū)動舔琅,我們這里只討論 MyCat 自己實(shí)現(xiàn)的 native
    String dbDriver = dataHostConfig.getDbDriver();
    // 1 為每一個(gè) <dataHost> 節(jié)點(diǎn)的 <writeHost> 節(jié)點(diǎn)創(chuàng)建一個(gè) PhysicalDatasource
    PhysicalDatasource[] writeSources = createDataSource(dataHostConfig, name, dbType, dbDriver, dataHostConfig.getWriteHosts(), false);

    Map<Integer, DBHostConfig[]> readHostsMap = dataHostConfig.getReadHosts();
    Map<Integer, PhysicalDatasource[]> readSourcesMap = new HashMap<Integer, PhysicalDatasource[]>(readHostsMap.size());
    // 對于每個(gè)讀節(jié)點(diǎn)建立 key 為 writeHost 下標(biāo) value 為 readHost 的 PhysicalDatasource[] 的哈希表
    for (Map.Entry<Integer, DBHostConfig[]> entry : readHostsMap.entrySet()) {
        // 2 為每一個(gè) <dataHost> 節(jié)點(diǎn)的 <readHost> 節(jié)點(diǎn)創(chuàng)建一個(gè) PhysicalDatasource
        PhysicalDatasource[] readSources = createDataSource(dataHostConfig, name, dbType, dbDriver, entry.getValue(), true);
        readSourcesMap.put(entry.getKey(), readSources);
    }

    // 3 初始化 PhysicalDBPool 并返回
    PhysicalDBPool pool = new PhysicalDBPool(dataHostConfig.getName(), dataHostConfig, writeSources, readSourcesMap, dataHostConfig.getBalance(), dataHostConfig.getWriteType());
    pool.setSlaveIDs(dataHostConfig.getSlaveIDs());
    return pool;
}

io.mycat.config.ConfigInitializer#createDataSource 完成具體的數(shù)據(jù)源創(chuàng)建等恐。根據(jù)不同的 dvTypedbDriver 創(chuàng)建不同的 PhysicalDatasource

  • dvType == mysql && dbDriver == native --> MySQLDataSource
  • dvType == mysql && dbDriver == jdbc --> JDBCDataSource
  • dvType == postgresql && dbDriver == native --> PostgreSQLDataSource
private PhysicalDatasource[] createDataSource(DataHostConfig dataHostConfig, String hostName, String dbType, String dbDriver, DBHostConfig[] nodes, boolean isRead) {
    PhysicalDatasource[] dataSources = new PhysicalDatasource[nodes.length];
    if ("mysql".equals(dbType) && "native".equals(dbDriver)) {
        for (int i = 0; i < nodes.length; i++) {
            //設(shè)置最大 idle 時(shí)間,默認(rèn)為 30 分鐘(可自定義)
            nodes[i].setIdleTimeout(system.getIdleTimeout());
            MySQLDataSource ds = new MySQLDataSource(nodes[i], dataHostConfig, isRead);
            dataSources[i] = ds;
        }
    } else if ("jdbc".equals(dbDriver)) {
        for (int i = 0; i < nodes.length; i++) {
            nodes[i].setIdleTimeout(system.getIdleTimeout());
            JDBCDatasource ds = new JDBCDatasource(nodes[i], dataHostConfig, isRead);
            dataSources[i] = ds;
        }
    } else if ("postgresql".equalsIgnoreCase(dbType) && dbDriver.equalsIgnoreCase("native")) {
        for (int i = 0; i < nodes.length; i++) {
            nodes[i].setIdleTimeout(system.getIdleTimeout());
            PostgreSQLDataSource ds = new PostgreSQLDataSource(nodes[i], dataHostConfig, isRead);
            dataSources[i] = ds;
        }
    } else {
        throw new ConfigException("not supported yet !" + hostName);
    }
    return dataSources;
}

4.3 創(chuàng)建物理數(shù)據(jù)庫節(jié)點(diǎn)(PhysicalDBNode)

io.mycat.config.ConfigInitializer#initDataNodes 為每個(gè) <dataNode> 節(jié)點(diǎn)創(chuàng)建一個(gè) PhysicalDBNode备蚓,根據(jù) <dataNode> 節(jié)點(diǎn)的 dataHost 屬性值從 Map<String, PhysicalDBPool> dataHosts 中找到 <dataNode> 對應(yīng)的連接池课蔬,并賦予 PhysicalDBNode

private Map<String, PhysicalDBNode> initDataNodes(ConfigLoader configLoader) {
    Map<String, PhysicalDBNode> nodes = new HashMap<String, PhysicalDBNode>(dataNodeConfigMap.size());
    
    Map<String, DataNodeConfig> dataNodeConfigMap = configLoader.getDataNodes();
    for (DataNodeConfig dataNodeConfig : dataNodeConfigMap.values()) {
        // 根據(jù) dataHost 名稱獲取對應(yīng)的 PhysicalDBPool
        PhysicalDBPool pool = this.dataHosts.get(dataNodeConfig.getDataHost());
        PhysicalDBNode dataNode = new PhysicalDBNode(dataNodeConfig.getName(), dataNodeConfig.getDatabase(), pool);
        nodes.put(dataNode.getName(), dataNode);
    }
    return nodes;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市郊尝,隨后出現(xiàn)的幾起案子二跋,更是在濱河造成了極大的恐慌,老刑警劉巖流昏,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扎即,死亡現(xiàn)場離奇詭異吞获,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铺遂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門衫哥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茎刚,“玉大人襟锐,你說我怎么就攤上這事√哦В” “怎么了粮坞?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長初狰。 經(jīng)常有香客問我莫杈,道長,這世上最難降的妖魔是什么奢入? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任筝闹,我火速辦了婚禮,結(jié)果婚禮上腥光,老公的妹妹穿的比我還像新娘关顷。我一直安慰自己,他們只是感情好武福,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布议双。 她就那樣靜靜地躺著,像睡著了一般捉片。 火紅的嫁衣襯著肌膚如雪平痰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天伍纫,我揣著相機(jī)與錄音宗雇,去河邊找鬼。 笑死莹规,一個(gè)胖子當(dāng)著我的面吹牛赔蒲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播访惜,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼嘹履,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了债热?” 一聲冷哼從身側(cè)響起砾嫉,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窒篱,沒想到半個(gè)月后焕刮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舶沿,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年配并,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了括荡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡溉旋,死狀恐怖畸冲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情观腊,我是刑警寧澤邑闲,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站梧油,受9級特大地震影響苫耸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜儡陨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一褪子、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧骗村,春花似錦嫌褪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至信轿,卻和暖如春晃痴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背财忽。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工倘核, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人即彪。 一個(gè)月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓紧唱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親隶校。 傳聞我的和親對象是個(gè)殘疾皇子漏益,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

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

  • NoSQL 根本性的優(yōu)勢在于在云計(jì)算時(shí)代,簡單深胳、易于大規(guī)模分布式擴(kuò)展绰疤,并且讀寫性能非常高 關(guān)系型數(shù)據(jù)庫NoSQL ...
    Q南南南Q閱讀 503評論 0 7
  • 為什么需要讀寫分離 至于為什么需要讀寫分離,在我之前的文章有介紹過了舞终,相信看到這篇文章的人也知道為什么需要讀寫分離...
    Raye閱讀 1,337評論 0 6
  • 對于任何框架而言,在使用前都要進(jìn)行一系列的初始化余爆,MyBatis也不例外纷宇。本章將通過以下幾點(diǎn)詳細(xì)介紹MyBatis...
    java成功之路閱讀 564評論 0 1
  • MyCat配置詳解 MyCAT 配置解析 server.xml Mycat的配置文件,設(shè)置賬號蛾方、參數(shù)等schema...
    呆萌孫先生閱讀 402評論 0 0
  • 基于 Mycat 1.6.7.3 版本 為什么要分庫分表 1像捶、數(shù)據(jù)庫性能瓶頸的出現(xiàn)1)對于應(yīng)用來說,如果數(shù)據(jù)庫性能...
    vincent浩哥閱讀 845評論 0 0