GroupDataSource 负责一组 db节点,包含多个SingleDataSource, 将它们分为一个主和多个从进行读写分离和多个从库的负载均衡; 对应db部署架构的话 对应一个分库 或 一主多从
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 {
// 权限检查,根据配置判断当前应用是否有db的访问权限
this.securityCheck();
// 初始化配置相关的组件
this.initConfig();
// 加载自定义jdbcFilter过滤器
this.initFilters();
// 逐个执行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();
}
// 记录下启动次数
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 单数据的源管理器
// 启动监控线程任务 CloseDataSourceTask, 不断轮训待关闭的SingleDataSource(配置刷新后 老的ds或者主动关闭的ds)
SingleDataSourceManagerFactory.getDataSourceManager().init();
// 初始化主库和从库的SingleDataSource
initDataSources();
// 初始化读写策略,可以强指定读master
initReadWriteStrategy();
// 将GroupDataSource自身加入到 配置刷新列表中,每隔60秒会检查一次配置,如果发生变更的话会重新拉取配置 重建sds
DataSourceConfigRefresh.getInstance().register(this);
LOGGER.info(String.format("GroupDataSource(%s) successfully initialized.", jdbcRef));
}
#initDataSource(); 初始化数据源,会将读写数据源单独初始化
private void initDataSources() {
try {
// 初始化读库数据源,连接获取的时候读库间根据权重负载均衡 选择SingleDataSource
this.**readDataSource** = new LoadBalancedDataSource(getLoadBalancedConfig(groupConfig.getDataSourceConfigs()),
this.filters, systemConfigManager.getSystemConfig(), this.configManagerType, this.configService,
groupConfig.getRouterStrategy());
this.readDataSource.init();
// 初始化写库(master)数据源 快速失败
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 也是实现了DataSource的,它包裹分组内所有从库的 SingleDataSource 根据负载策略选取 sds
- FailOverDataSource 同样实现了DataSource,它包裹写库的 SingleDataSource
这两个算是装饰模式
完整目录:数据库中间件zebra源码分析