GroupDataSource 負責一組 db節(jié)點刮萌,包含多個SingleDataSource驮配, 將它們分為一個主和多個從進行讀寫分離和多個從庫的負載均衡; 對應db部署架構(gòu)的話 對應一個分庫 或 一主多從
shardDataSource分庫分表中的分庫對應的就是 GroupDataSource着茸,也可單獨讀寫分離壮锻、負載均衡使用
初始化過程 GroupDataSource#init()
public synchronized void init() {
if (StringUtils.isBlank(jdbcRef)) {
throw new ZebraException("jdbcRef cannot be empty");
}
this.checkJdbcRefInitializationTimes();
if (init) {
throw new ZebraException(String.format("GroupDataSource [%s] is already initialized once.", jdbcRef));
} else {
this.init = true;
}
try {
// 權(quán)限檢查,根據(jù)配置判斷當前應用是否有db的訪問權(quán)限
this.securityCheck();
// 初始化配置相關(guān)的組件
this.initConfig();
// 加載自定義jdbcFilter過濾器
this.initFilters();
// 逐個執(zhí)行jdbcFilter過濾器 initGroupDataSource
if (filters != null && filters.size() > 0) {
JdbcFilter chain = new DefaultJdbcFilterChain(filters) {
@Override
public void initGroupDataSource(GroupDataSource source, JdbcFilter chain) {
if (index < filters.size()) {
filters.get(index++).initGroupDataSource(source, chain);
} else {
// 開始初始化
source.initInternal();
}
}
};
chain.initGroupDataSource(this, chain);
} else {
// 開始初始化
initInternal();
}
// 記錄下啟動次數(shù)
this.recordJdbcRefInitializationTimes();
} catch (Exception e) {
String errorMsg = "init GroupDataSource[" + jdbcRef + "] error!";
LOGGER.error(errorMsg, e);
throw new ZebraException(errorMsg, e);
}
}
開始初始化 #initInternal()
protected void initInternal() {
// 初始化 SingleDataSource 單數(shù)據(jù)的源管理器
// 啟動監(jiān)控線程任務 CloseDataSourceTask, 不斷輪訓待關(guān)閉的SingleDataSource(配置刷新后 老的ds或者主動關(guān)閉的ds)
SingleDataSourceManagerFactory.getDataSourceManager().init();
// 初始化主庫和從庫的SingleDataSource
initDataSources();
// 初始化讀寫策略涮阔,可以強指定讀master
initReadWriteStrategy();
// 將GroupDataSource自身加入到 配置刷新列表中猜绣,每隔60秒會檢查一次配置,如果發(fā)生變更的話會重新拉取配置 重建sds
DataSourceConfigRefresh.getInstance().register(this);
LOGGER.info(String.format("GroupDataSource(%s) successfully initialized.", jdbcRef));
}
#initDataSource(); 初始化數(shù)據(jù)源敬特,會將讀寫數(shù)據(jù)源單獨初始化
private void initDataSources() {
try {
// 初始化讀庫數(shù)據(jù)源掰邢,連接獲取的時候讀庫間根據(jù)權(quán)重負載均衡 選擇SingleDataSource
this.**readDataSource** = new LoadBalancedDataSource(getLoadBalancedConfig(groupConfig.getDataSourceConfigs()),
this.filters, systemConfigManager.getSystemConfig(), this.configManagerType, this.configService,
groupConfig.getRouterStrategy());
this.readDataSource.init();
// 初始化寫庫(master)數(shù)據(jù)源 快速失敗
this.**writeDataSource** = new FailOverDataSource(getFailoverConfig(groupConfig.getDataSourceConfigs()),
this.filters);
this.writeDataSource.init();
} catch (RuntimeException e) {
try {
this.close(this.readDataSource, this.writeDataSource);
} catch (SQLException ignore) {
}
throw new ZebraException("fail to initialize group dataSource [" + jdbcRef + "]", e);
}
}
- LoadBalancedDataSource 也是實現(xiàn)了DataSource的牺陶,它包裹分組內(nèi)所有從庫的 SingleDataSource 根據(jù)負載策略選取 sds
- FailOverDataSource 同樣實現(xiàn)了DataSource,它包裹寫庫的 SingleDataSource
這兩個算是裝飾模式