本系列的原码对应:ShardingSphere-5.0.0-beta
简介
今天接着研究shardingSphere原码,还是从官方examples开始着手研究sharding proxy。开始原码研究之前,让我们先来了解下什么是sharding proxy。
顾名思义,当看到proxy自然而然的就想到了代理模式,其实sharding proxy 就是一种代理,不过是对数据库的代理。定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。目前支持 MySQL 和 PostgreSQL 数据库。
sharding jdbc是针对java语言的驱动包,是代码侵入式的,意为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。sharding proxy 追求的则是对数据库的代理,是代码零侵入式,只需要改动数据库配置即可。
sharding proxy 服务
通过官网了解到 sharding proxy 是一个单独的中间件服务,我们需要先启动该服务才能开始愉快的玩耍
这次我们需要先来启动原码中的proxy子项,后面我们会将其称为proxy服务端
在shardingsphere-proxy->shardingsphere-proxy-bootstrap->Bootstrap类
启动之前按照官网指示先对config-xxx.yaml、server.yaml 进行修改。
server.yaml
rules:
- !AUTHORITY
users:
- root@%:root
- sharding@:sharding
provider:
type: NATIVE
props:
max-connections-size-per-query: 1
executor-size: 16 # Infinite by default.
proxy-frontend-flush-threshold: 128 # The default value is 128.
# LOCAL: Proxy will run with LOCAL transaction.
# XA: Proxy will run with XA transaction.
# BASE: Proxy will run with B.A.S.E transaction.
proxy-transaction-type: LOCAL
xa-transaction-manager-type: Atomikos
proxy-opentracing-enabled: false
proxy-hint-enabled: false
sql-show: true
check-table-metadata-enabled: false
lock-wait-timeout-milliseconds: 50000 # The maximum time to wait for a lock
show-process-list-enabled: false
# Proxy backend query fetch size. A larger value may increase the memory usage of ShardingSphere Proxy.
# The default value is -1, which means set the minimum value for different JDBC drivers.
proxy-backend-query-fetch-size: -1
check-duplicate-table-enabled: fals
相关的配置文件位于:resources/conf 目录下
我们只修改了server.yaml,并未对config-xxx.yaml进行修改,是因为得按照测试需要针对不同的文件进行修改,我们在sharding proxy 客户端中来进行说明。
proxy的默认端口为3307,后面客户端连接需要用到
sharding proxy 客户端
我会把example中的测试端统称为客户端
使用官方实例example->shardingsphere-proxy-example->ProxySpringBootStarterExample类来进行测试
首先约定大于配置,我们要对application.properties文件进行修改,配置成proxy服务器的连接(对于我们来说proxy就是真实的mysql服务器,并不需要知道代理的存在,代理模式的意义。)
mybatis.config-location=classpath:META-INF/mybatis-config.xml
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3307/sharding_db?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
这里提一下,在ProxySpringBootStarterExample类上的注解非常贴心的告诉我们如果想要跑测试类,需要先做什么,我也是在跑测试的时候根据提示去了解proxy应该如何测试的。
/*
* 1. Copy resources/conf/*.yaml to ShardingSphere-Proxy conf folder and overwrite original file.
*
* If you want to use sharding, please select config-sharding.yaml
* If you want to use replica-query, please select config-readwrite-splitting.yaml
*
* 2. Please make sure ShardingSphere-Proxy is running before you run this example.
*/
1、分库分表示例
我们可以开始修改sharding proxy 服务端的config-xxx.yaml配置文件了
我们放开配置yaml文件中的配置:shardingsphere-proxy/shardingsphere-proxy-bootstrap/src/main/resources/conf/config-sharding.yaml
放开其配置即可,然后修改url和密码等配置信息,大致如下:
记住我们的数据库的逻辑数据库是: sharding_db
schemaName: sharding_db
dataSources:
ds_0:
url: jdbc:mysql://192.168.0.111:3310/demo_ds_0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
ds_1:
url: jdbc:mysql://192.168.0.111:3310/demo_ds_1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !SHARDING
tables:
t_order:
actualDataNodes: ds_${0..1}.t_order_${0..1}
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: t_order_inline
keyGenerateStrategy:
column: order_id
keyGeneratorName: snowflake
t_order_item:
actualDataNodes: ds_${0..1}.t_order_item_${0..1}
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: t_order_item_inline
keyGenerateStrategy:
column: order_item_id
keyGeneratorName: snowflake
bindingTables:
- t_order,t_order_item
defaultDatabaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: database_inline
defaultTableStrategy:
none:
shardingAlgorithms:
database_inline:
type: INLINE
props:
algorithm-expression: ds_${user_id % 2}
t_order_inline:
type: INLINE
props:
algorithm-expression: t_order_${order_id % 2}
t_order_item_inline:
type: INLINE
props:
algorithm-expression: t_order_item_${order_id % 2}
keyGenerators:
snowflake:
type: SNOWFLAKE
props:
worker-id: 123
配置完成后,proxy服务端重启
客户端的application.properties配置需要针对服务端的schemaName内进行相应修改
启动后,我们就看到相关的ShardingSphere Proxy的日志:
能够看到通过模2,将数据分片写入了不同的数据库
最开始在调试的时候没有注意到processSuccess方法加了事务处理,当整个事务没走完的时候,insert是不会被数据库真正执行的,所以每次插入直接查询数据库中是没有数据的,然后走了删除方法整个运行完,事务提交后,数据库中还是没有数据。这块想了很久一直以为是proxy中需要开启某些设置,后来才发现是processSuccess开启了事务导致的。为了测试是不需要开启事务的,将@Transactional注释掉即可。
2、读写分离示例
我们放开配置yaml文件中的配置:shardingsphere-proxy/shardingsphere-proxy-bootstrap/src/main/resources/conf/config-readwrite-splitting.yaml
放开其配置即可,然后修改url和密码等配置信息,大致如下:
记住我们的数据库是: readwrite_splitting_db
schemaName: readwrite_splitting_db
dataSources:
write_ds:
url: jdbc:mysql://192.168.10.135:3310/demo_write_ds?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_0:
url: jdbc:mysql://192.168.10.135:3311/demo_write_ds?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !READWRITE_SPLITTING
dataSources:
pr_ds:
writeDataSourceName: write_ds
readDataSourceNames:
- read_ds_0
配置完成后,proxy服务端重启
客户端的application.properties配置需要针对服务端的schemaName内进行相应修改
启动后,我们断点查看:还是老套路,先将从库表里的数据进行删除,主库中的数据不变:
输出日志,显示的是从库中的数据,证明读写分离成功:
3、加密示例
我们放开配置yaml文件中的配置:shardingsphere-proxy/shardingsphere-proxy-bootstrap/src/main/resources/conf/config-encrypt_db.yaml
放开其配置即可,然后修改url和密码等配置信息,大致如下:
记住我们的数据库是: encrypt_db
schemaName: encrypt_db
dataSources:
ds_0:
url: jdbc:mysql://192.168.0.111:3310/demo_ds_0?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !ENCRYPT
tables:
t_user:
columns:
user_name:
cipherColumn: user_name
encryptorName: aes_encryptor
pwd:
cipherColumn: pwd
encryptorName: md5_encryptor
encryptors:
aes_encryptor:
type: AES
props:
aes-key-value: 123456abc
md5_encryptor:
type: MD5
配置完成后,proxy服务端重启
客户端的application.properties配置需要针对服务端的schemaName内进行相应修改 修改客户端启动类:ProxySpringBootStarterExample中getBean,通过名称进行注入
private static ExampleService getExampleService(final ConfigurableApplicationContext applicationContext) {
return applicationContext.getBean("encrypt",ExampleService.class);
}
修改mybatis-config.xml配置文件,加入UserMapper.xml
启动后,我们断点查看数据库:
总结
本次主要是通过对examples模块中的harding proxy的运行,了解了proxy 和jdbc的区别,通过修改proxy服务器配置测试了分库分表、读写分离、密码加密等功能。在测试中发现jdbc和proxy里面共用了很多shardingsphere里面的公共功能。