说明
路由引擎主要使用上下文环境中的配置,配置信息由解析引擎生成的语法树和分库分表相关信息组成。路由引擎会根据是否携带分片键等不同规则,进行不同的路由选择,如下图:
public ExecutionContext generateExecutionContext(final LogicSQL logicSQL, final ShardingSphereMetaData metaData, final ConfigurationProperties props) {
//路由
RouteContext routeContext = route(logicSQL, metaData, props);
//重写
SQLRewriteResult rewriteResult = rewrite(logicSQL, metaData, props, routeContext);
//执行
ExecutionContext result = createExecutionContext(logicSQL, metaData, routeContext, rewriteResult);
//日志
logSQL(logicSQL, props, result);
return result;
}
private RouteContext route(final LogicSQL logicSQL, final ShardingSphereMetaData metaData, final ConfigurationProperties props) {
//创建路由引擎,并调用路由方法
return new SQLRouteEngine(metaData.getRuleMetaData().getRules(), props).route(logicSQL, metaData);
}
public RouteContext route(final LogicSQL logicSQL, final ShardingSphereMetaData metaData) {
//判断sql是否需要全库执行,创建全库的路由执行器或部分的路由执行器
SQLRouteExecutor executor = isNeedAllSchemas(logicSQL.getSqlStatementContext().getSqlStatement()) ? new AllSQLRouteExecutor() : new PartialSQLRouteExecutor(rules, props);
//调用路由方法
return executor.route(logicSQL, metaData);
}
全库路由类
public final class AllSQLRouteExecutor implements SQLRouteExecutor {
@Override
public RouteContext route(final LogicSQL logicSQL, final ShardingSphereMetaData metaData) {
RouteContext result = new RouteContext();
for (String each : metaData.getResource().getDataSources().keySet()) {
result.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList()));
}
return result;
}
}
部分路由类
public final class PartialSQLRouteExecutor implements SQLRouteExecutor {
static {
ShardingSphereServiceLoader.register(SQLRouter.class);
}
private final ConfigurationProperties props;
@SuppressWarnings("rawtypes")
private final Map<ShardingSphereRule, SQLRouter> routers;
public PartialSQLRouteExecutor(final Collection<ShardingSphereRule> rules, final ConfigurationProperties props) {
this.props = props;
routers = OrderedSPIRegistry.getRegisteredServices(SQLRouter.class, rules);
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public RouteContext route(final LogicSQL logicSQL, final ShardingSphereMetaData metaData) {
RouteContext result = new RouteContext();
for (Entry<ShardingSphereRule, SQLRouter> entry : routers.entrySet()) {
if (result.getRouteUnits().isEmpty()) {
result = entry.getValue().createRouteContext(logicSQL, metaData, entry.getKey(), props);
} else {
entry.getValue().decorateRouteContext(result, logicSQL, metaData, entry.getKey(), props);
}
}
if (result.getRouteUnits().isEmpty() && 1 == metaData.getResource().getDataSources().size()) {
String singleDataSourceName = metaData.getResource().getDataSources().keySet().iterator().next();
result.getRouteUnits().add(new RouteUnit(new RouteMapper(singleDataSourceName, singleDataSourceName), Collections.emptyList()));
}
return result;
}
}