工厂类ShardingDataSourceFactory.createDataSource()
方法在创建Sharding-JDBC的数据源实现类ShardingDataSource
的同时还创建了ShardingRule
、ShardingRuntimeContext
两个核心类的对象,如下相关源码:
public final class ShardingDataSourceFactory {
/**
* Create sharding data source.
*
* @param dataSourceMap data source map
* @param shardingRuleConfig rule configuration for databases and tables sharding
* @param props properties for data source
* @return sharding data source
* @throws SQLException SQL exception
*/
public static DataSource createDataSource(
final Map<String, DataSource> dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
}
}
public class ShardingDataSource extends AbstractDataSourceAdapter {
private final ShardingRuntimeContext runtimeContext;
public ShardingDataSource(final Map<String, DataSource> dataSourceMap, final ShardingRule shardingRule, final Properties props) throws SQLException {
super(dataSourceMap);
checkDataSourceType(dataSourceMap);
runtimeContext = new ShardingRuntimeContext(dataSourceMap, shardingRule, props, getDatabaseType());
}
}
ShardingDataSource
持有属性ShardingRuntimeContext
,这里面又有两个重要属性DatabaseMetaData
(数据库元数据信息)和ShardingSphereMetaData
(元数据信息,包含数据源的元数据信息和表的元数据信息)。
ShardingRule
保存了表的分库分表配置,这些配置包括分库策略以及算法、分表策略以及算法,也就是说根据一个表以及这个表的列可以从ShardingRuntimeContext
中获取这个表的分库分表策略和算法。
ShardingSphereMetaData
则维护了数据源和表的元数据信息,其有两个属性:DataSourceMetas
和TableMetas
,分表表示数据源的元数据信息和表的元数据信息。
ShardingRuleConfiguration
是分库分表配置的核心和入口,它可以包含多个TableRuleConfiguration
和MasterSlaveRuleConfiguration
。每一组相同规则分片的表配置一个TableRuleConfiguration
。一个TableRuleConfiguration
表示一个表的分库分表策略配置,其持有两个类型为ShardingStrategyConfiguration
的属性:defaultDatabaseShardingStrategyConfig
和defaultTableShardingStrategyConfig
,分别表示分库策略配置和分表策略配置。ShardingStrategyConfiguration
有如下五种实现:
具体为:
StandardShardingStrategyConfiguration
支持精确分片和范围分片
ComplexShardingStrategyConfiguration
支持复杂分表
HintShardingStrategyConfiguration
强制某种策略分片
InlineShardingStrategyConfiguration
支持表达式分片
NoneShardingStrategyConfiguration
不分片
以上每种分片策略配置都关联一到两个对应的分片算法
分片算法由接口ShardingAlgorithm
表示,其抽象子类有:
PreciseShardingAlgorithm
精确分片算法
RangeShardingAlgorithm
范围分片算法
HintShardingAlgorithm
强制分片算法
ComplexKeysShardingAlgorithm
复杂分片算法
Sharding-JDBC会使用ShardingRuleConfiguration
实例化TableRule
对象,源码如下:
public class ShardingRule implements BaseRule {
private final ShardingRuleConfiguration ruleConfiguration;
private final ShardingDataSourceNames shardingDataSourceNames;
private final Collection<TableRule> tableRules;
private final Collection<BindingTableRule> bindingTableRules;
private final Collection<String> broadcastTables;
private final ShardingStrategy defaultDatabaseShardingStrategy;
private final ShardingStrategy defaultTableShardingStrategy;
private final ShardingKeyGenerator defaultShardingKeyGenerator;
private final Collection<MasterSlaveRule> masterSlaveRules;
private final EncryptRule encryptRule;
public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> dataSourceNames) {
Preconditions.checkArgument(null != shardingRuleConfig, "ShardingRuleConfig cannot be null.");
Preconditions.checkArgument(null != dataSourceNames && !dataSourceNames.isEmpty(), "Data sources cannot be empty.");
this.ruleConfiguration = shardingRuleConfig;
shardingDataSourceNames = new ShardingDataSourceNames(shardingRuleConfig, dataSourceNames);
tableRules = createTableRules(shardingRuleConfig);
broadcastTables = shardingRuleConfig.getBroadcastTables();
bindingTableRules = createBindingTableRules(shardingRuleConfig.getBindingTableGroups());
defaultDatabaseShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultDatabaseShardingStrategyConfig());
defaultTableShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultTableShardingStrategyConfig());
defaultShardingKeyGenerator = createDefaultKeyGenerator(shardingRuleConfig.getDefaultKeyGeneratorConfig());
masterSlaveRules = createMasterSlaveRules(shardingRuleConfig.getMasterSlaveRuleConfigs());
encryptRule = createEncryptRule(shardingRuleConfig.getEncryptRuleConfig());
}
}
一个TableRule
对象表示一个逻辑表的库表资源,其维护一个类型为DataNode
的集合属性actualDataNodes
:
这个DataNode集合actualDataNodes
表示该逻辑表对应的实际库表的集合,比如现在有两个库db0
、db1
,每个库有两个表,逻辑表名为tborder,那么TableRule对象的属性actualDataNodes
则有4个元素:
db0 tborder0
db0 tborder1
db1 tborder0
db1 tborder1
Sharding-JDBC做路由时就根据这个集合使用相应的算法进行实际的库表选取的。
程序的入口是org.apache.shardingsphere.shardingproxy.Bootstrap
:
public static void main(final String[] args) throws IOException, SQLException {
ShardingConfiguration shardingConfig = new ShardingConfigurationLoader().load();
logRuleConfigurationMap(getRuleConfiguration(shardingConfig.getRuleConfigurationMap()).values());
int port = getPort(args);
if (null == shardingConfig.getServerConfiguration().getOrchestration()) {
startWithoutRegistryCenter(shardingConfig.getRuleConfigurationMap(), shardingConfig.getServerConfiguration().getAuthentication(), shardingConfig.getServerConfiguration().getProps(), port);
} else {
startWithRegistryCenter(shardingConfig.getServerConfiguration(), shardingConfig.getRuleConfigurationMap().keySet(), shardingConfig.getRuleConfigurationMap(), port);
}
}
public final class ShardingConfigurationLoader {
public ShardingConfiguration load() throws IOException {
Collection<String> schemaNames = new HashSet<>();
YamlProxyServerConfiguration serverConfig = loadServerConfiguration(new File(ShardingConfigurationLoader.class.getResource(CONFIG_PATH + SERVER_CONFIG_FILE).getFile()));
File configPath = new File(ShardingConfigurationLoader.class.getResource(CONFIG_PATH).getFile());
Collection<YamlProxyRuleConfiguration> ruleConfigurations = new LinkedList<>();
for (File each : findRuleConfigurationFiles(configPath)) {
Optional<YamlProxyRuleConfiguration> ruleConfig = loadRuleConfiguration(each, serverConfig);
if (ruleConfig.isPresent()) {
Preconditions.checkState(schemaNames.add(ruleConfig.get().getSchemaName()), "Schema name `%s` must unique at all rule configurations.", ruleConfig.get().getSchemaName());
ruleConfigurations.add(ruleConfig.get());
}
}
Preconditions.checkState(!ruleConfigurations.isEmpty() || null != serverConfig.getOrchestration(), "Can not find any sharding rule configuration file in path `%s`.", configPath.getPath());
Map<String, YamlProxyRuleConfiguration> ruleConfigurationMap = new HashMap<>(ruleConfigurations.size(), 1);
for (YamlProxyRuleConfiguration each : ruleConfigurations) {
ruleConfigurationMap.put(each.getSchemaName(), each);
}
return new ShardingConfiguration(serverConfig, ruleConfigurationMap);
}
}
private static void startWithoutRegistryCenter(final Map<String, YamlProxyRuleConfiguration> ruleConfigs,
final YamlAuthenticationConfiguration authentication, final Properties prop, final int port) throws SQLException {
Authentication authenticationConfiguration = getAuthentication(authentication);
ConfigurationLogger.log(authenticationConfiguration);
ConfigurationLogger.log(prop);
ShardingProxyContext.getInstance().init(authenticationConfiguration, prop);
LogicSchemas.getInstance().init(getDataSourceParameterMap(ruleConfigs), getRuleConfiguration(ruleConfigs));
initOpenTracing();
ShardingProxy.getInstance().start(port);
}
private static void startWithRegistryCenter(final YamlProxyServerConfiguration serverConfig,
final Collection<String> shardingSchemaNames, final Map<String, YamlProxyRuleConfiguration> ruleConfigs, final int port) {
try (ShardingOrchestrationFacade shardingOrchestrationFacade = new ShardingOrchestrationFacade(
new OrchestrationConfigurationYamlSwapper().swap(serverConfig.getOrchestration()), shardingSchemaNames)) {
initShardingOrchestrationFacade(serverConfig, ruleConfigs, shardingOrchestrationFacade);
Authentication authentication = shardingOrchestrationFacade.getConfigService().loadAuthentication();
Properties properties = shardingOrchestrationFacade.getConfigService().loadProperties();
ConfigurationLogger.log(authentication);
ConfigurationLogger.log(properties);
ShardingProxyContext.getInstance().init(authentication, properties);
LogicSchemas.getInstance().init(shardingSchemaNames, getSchemaDataSourceParameterMap(shardingOrchestrationFacade), getSchemaRules(shardingOrchestrationFacade), true);
initOpenTracing();
ShardingProxy.getInstance().start(port);
} catch (SQLException e) {
e.printStackTrace();
}
}
1.首先执行load()
load()
方法主要是进行加载conf目录下的文件内容,构建ShardingConfiguration
对象,这个对象有两个属性:
public final class ShardingConfiguration {
private final YamlProxyServerConfiguration serverConfiguration;
private final Map<String, YamlProxyRuleConfiguration> ruleConfigurationMap;
}
服务配置相关参数serverConfiguration
,主要是加载server.yaml
得到的对象;
规则集合ruleConfigurationMap
,保存的是逻辑库对应的规则信息。
2.根据配置决定是有注册中心的加载还是没有注册中心的加载。
以有注册中心为例,也就是startWithRegistryCenter
函数,这里
initShardingOrchestrationFacade()
会将读到的配置——也就是服务配置信息以及规则配置等信息加载到注册中心,接下来LogicSchemas.getInstance().init()
方法将逻辑库信息加载到内存,也就是保存到LogicSchemas中的属性Map
关键的属性是shardingRule
,以及backendDataSource
。ShardingRule
保存了表的分库分表配置,这些配置包括分库策略以及算法、分表策略以及算法,也就是说根据一个表以及这个表的列可以从ShardingRuntimeContext
中获取这个表的分库分表策略和算法。backendDataSource
则保存了数据源。