3、ShardingSphere之测试 proxy

1,136 阅读6分钟

本系列的原码对应:ShardingSphere-5.0.0-beta

简介

今天接着研究shardingSphere原码,还是从官方examples开始着手研究sharding proxy。开始原码研究之前,让我们先来了解下什么是sharding proxy。

顾名思义,当看到proxy自然而然的就想到了代理模式,其实sharding proxy 就是一种代理,不过是对数据库的代理。定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。目前支持 MySQL 和 PostgreSQL 数据库。

sharding jdbc是针对java语言的驱动包,是代码侵入式的,意为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。sharding proxy 追求的则是对数据库的代理,是代码零侵入式,只需要改动数据库配置即可。

image.png

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,后面客户端连接需要用到

image.png

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内进行相应修改

image.png

启动后,我们就看到相关的ShardingSphere Proxy的日志:

image.png

能够看到通过模2,将数据分片写入了不同的数据库

image.png

最开始在调试的时候没有注意到processSuccess方法加了事务处理,当整个事务没走完的时候,insert是不会被数据库真正执行的,所以每次插入直接查询数据库中是没有数据的,然后走了删除方法整个运行完,事务提交后,数据库中还是没有数据。这块想了很久一直以为是proxy中需要开启某些设置,后来才发现是processSuccess开启了事务导致的。为了测试是不需要开启事务的,将@Transactional注释掉即可。

image.png

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内进行相应修改

启动后,我们断点查看:还是老套路,先将从库表里的数据进行删除,主库中的数据不变:

image.png

image.png

输出日志,显示的是从库中的数据,证明读写分离成功:

image.png

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);
}

image.png 修改mybatis-config.xml配置文件,加入UserMapper.xml

image.png

启动后,我们断点查看数据库:

image.png

总结

本次主要是通过对examples模块中的harding proxy的运行,了解了proxy 和jdbc的区别,通过修改proxy服务器配置测试了分库分表、读写分离、密码加密等功能。在测试中发现jdbc和proxy里面共用了很多shardingsphere里面的公共功能。