总文档 :文章目录
Github : github.com/black-ant
一 . 前言
本来没准备看这部分源码的, 事情的起因是因为之前一直在使用 3.0 的版本 ,这次看到5.0了想试试 ,结果没有跑起来, 官方文档又不给力 ,索性把源码看了一遍 , 把问题找到了…..
二 . 事情的起点
起因是因为使用 shardingsphere-jdbc-core-spring-boot-starter 依赖 , 想直接通过配置文件完成所有的配置 , 但是整个流程出现了不少问题 .
幸运的是之前写过一个 Bean 配置的 , 正好可以对比看看整个流程的问题.
2.1 Java Bean 配置方式
这里先将 Java Bean 配置的整个流程贴上来 , 用于对比 .2者都是使用 JPA 作为持久化框架
Maven 配置
1 | xml复制代码<dependency> |
Config 配置
1 | java复制代码@Configuration |
实体类
1 | java复制代码@Entity |
三 . Properties 配置方式
为了避免误导 , 配置文件在最后贴 ,我们从异常开始看起
java.util.NoSuchElementException: No value bound
这是第一个出现的异常 , 看异常栈里面 , 有这样几个重要的提示 :
1 | java复制代码Caused by: java.lang.reflect.InvocationTargetException: null |
3.1 多数据源
3.1.1 多数据源的加载
1 | java复制代码// 核心的配置加载来自于 org.apache.shardingsphere.spring.boot 包下 , 配置了如下 |
PS_M11_01_1 : 传入的资源依赖于 spring.shardingsphere.datasource.names 属性
可以看到 , 尽管我的配置中配置了 3 个 datasource , 但是最终使用的依赖于属性 spring.shardingsphere.datasource.names.
1 | java复制代码 |
3.1.2 多数据源总结
起点 : SpringBootConfiguration
处理核心 : ShardingSphereDataSourceFactory#createDataSource
构建单元 : ShardingSphereDataSource
扫描类 : DataSourceMapSetter
一句话总结 :
- SpringBootConfiguration 实现了EnvironmentAware 方法 , 则在容器加载的同时 , 会默认调用 SpringBootConfiguration 中 setEnvironment 方法
- setEnvironment 方法会扫描配置文件中的 Datasourse 配置 ,放入 一个集合 dataSourceMap
- SpringBootConfiguration 在使用 shardingSphereDataSource 加载多数据源时 , 使用该 Map
- shardingSphereDataSource 方法调用 ShardingSphereDataSourceFactory 创建数据源
- ShardingSphereDataSourceFactory 最终会构建出 ShardingSphereDataSource , 标识一个数据源
3.2 分库分表策略配置
配置跑通后 , 又出现了问题 :
java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
运行时抛出如上异常 , 虽然说的时 SQL 问题 , 但是直觉告诉我 , 这还是配置出现了偏差
于是按照如下步骤进行排查 :
1 | java复制代码// Step 1 : PreparedStatement # checkBounds |
这其实就是一个配置问题 , 但是 Sharding 返回的异常信息是看不出来原因的 .
总结
主要注意其中 C79- ShardingRouteEngine / M79_05- route0 方法 , 改方法中有2个主要的方法 , 分库分表的核心判断就在该方法中
这里把策略的加载路径记录一下:
虽然是 properties ,但是使用的还是 yml 的加载类 , 不冲突
具体却什么配置 ,按照 YamlShardingRuleConfiguration 类去反推就大概知道了
1 | java复制代码 |
3.3 分库分表逻辑
很好 , 项目这里总算跑起来了 , 但是分库分表的功能并没有实现 , 运行时 , 四个表均创建了
Bebug 发现 , ShardingSpherePreparedStatement 的 result 中返回了四个数据
PS:M74_02_01
于是按照以下流程过了一遍分库分表的流程 :
可以看到 , 第一个入口类是 ShardingSpherePreparedStatement
Step 1 : ShardingSpherePreparedStatement
该类是一个入口类 , 相关的操作均可以从该类向下查找 :
- 核心一 : M74_01中获取的StatementExecuteUnit即为最终会执行的SQL , 这其中已经包含了需要运行的库(详见上图) , 所以 createExecutionContext 时 , 相关数据已经生成
- 核心二 : M74_01中preparedStatementExecutor.executeUpdate 发起执行
1 | java复制代码C74- ShardingSpherePreparedStatement |
知道了源头在 M74_01 中 , 继续向下找 -> M75_01
Step 2 : Rule 的主要处理逻辑
1 | java复制代码// 该类中只有一个方法 |
PS:M75_01_01 Rule 结构
可以看到 , 包括多数据源 , 分片规则 ,都已经在里面了
剩下的就简单了 , 找到之前处理的地方就行了
Step 3 : 一步步 Debug
1 | java复制代码C76- SQLRouteEngine |
这里也不详细说了 , 一步步debug 下来 , 发现是 M79_04- routeByShardingConditionsWithCondition 中缺少相关的策略 , 配置文件写法问题 , 补齐后 , 一切正常
最终配置文件
1 | properties复制代码server.port=8085 |
总结
Sharding-JDBC 分析中最麻烦的就是 lombok 表达式了 , debug 起来叫一个麻烦 , 还要一个个去配置 , 想想之前改掉了这个习惯还是比较庆幸的 .
整个过程中主要有3个节点 :
- SpringBootConfiguration
- ShardingRouteEngine
- StandardShardingStrategy
头尾中间都在这里了 , 以这三个节点去debug ,基本上问题就出来了
其中需要明白的是 : sharding-jdbc 会在策略执行完成后 , 生成多个 ExecuteUnit , 每一个 ExecuteUnit 即为一个数据库处理对象 , 会在对应的数据库/数据表中执行
后续再来看看他的分布式事务和读写分离的主要逻辑 , 这里先记这么多
本文转载自: 掘金