Spring Boot + ShardingSphere 踩坑记

最近在准备秋招,偷了个轮子项目之后想改个分表,于是有了这篇文章。

省流:请使用shardingsphere-jdbc 5.5.2,并根据官方5.5.2版本文档进行配置,不要使用starter。此外,如果希望使用INTERVAL分片算法,请在插入数据前将对应的字段(如create_time)手动进行赋值,否则会报错。

完整配置:

# sharding.yml
dataSources:
  ds0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: <your_datasrouce_url>
    username: <your_user_name>
    password: <your_password>

rules:
  - !SINGLE
    tables:
      - "*.*"
  - !SHARDING
    tables:
      data:
        actualDataNodes: ds0.data_${2024..2025}
        tableStrategy:
          standard:
            shardingColumn: create_time
            shardingAlgorithmName: create_time_interval
        keyGenerateStrategy:
          column: id
          keyGeneratorName: snowflake

    shardingAlgorithms:
      create_time_interval:
        type: INTERVAL
        props:
          datetime-pattern: "yyyy-MM-dd HH:mm:ss"
          datetime-lower: '2024-01-01 00:00:00'
          sharding-suffix-pattern: "yyyy"
          datetime-interval-amount: 1
          datetime-interval-unit: YEARS

    keyGenerators:
      snowflake:
        type: SNOWFLAKE

props:
  sql-show: true
# application.yml
spring:
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:sharding.yml

我很少用来形容一个东西,上一个能被我如此评价的是微信小程序,现在又多了一个ShardingSphere。

最史的东西莫过于官方文档。很难想象在5202年的今天,一个Apache顶级项目的文档能够如此糟糕——哪怕是微信小程序在经过更新后,如今的文档已经勉强够看了,而在我看来ShardingSphere的文档甚至连更新前的微信小程序文档都远远不如,以至于我浪费了整整两天时间在毫无意义的试错与改配置上。

目前网上的大多数材料都是基于starter的,并且LLM给出的配置也大多基于starter,但是只要从官方网站点进官方文档,里面根本找不到配置starter的说明,只有人为地在搜索引擎里把ShardingSphere和Spring Boot一起搜索,才会找到一个有Spring Boot Starter配置的文档——而当你从官方的文档库里点进这个版本的文档,Spring Boot Starter这一项又会神秘消失。

按照好不容易找到的starter配置说明改好,点击启动后又会被各种莫名其妙的错误折磨,我遇到的包括但不限于提示内存泄漏启动不了、Hikari连接超时、明明配置了但框架拿到的属性值为null等。

于是开始考虑对starter进行降级,从被官方雪藏的v4.x的文档里翻出starter的配置说明并辛辛苦苦改好后,又遇到了各种莫名其妙的错误导致业务逻辑跑不通。

之后去Github上翻Issue,维护者直接告诉你starter不维护了,反手把Issue关了。

然后根据开发者的建议换成jdbc方式,发现按照官方文档给的JDBC启动流程根本跑不起来。当然并不是所有版本都是这样——只不过我恰好用的是跑不起来的版本。

之后我无计可施,只能挨个尝试不同版本——索性我是幸运的,用之前starter的版本试了两三次之后换上最新版就好了。

这个过程中,有些版本能用搜索引擎搜出来Spring Boot的配置方法,有些版本搜不出来。但你别想着大版本号下的配置格式是一致的——因为哪怕只是一个小版本的更新,配置格式都需要跟着一起修改,简直让人匪夷所思,更别提数据源的名称一会儿是url,一会儿又变成jdbc_url,我完全搞不懂这个名称有什么升级的意义。

务实一点,我劝你们,把文档,版本号的这个理念先搞懂。starter用的蛮好的,你去把他废弃了干什么,你文档不更新,应用起不来,你倒告诉我怎么解释,脸都不要了。

<think>我们正在讨论的是ApacheShardingSphere5.5.2的Proxy组件如何配置自定义SPI扩展。首先,需要了解ShardingSphere的SPI(ServiceProviderInterface)机制。在ShardingSphere中,很多功能都是通过SPI扩展的,比如分布式主键生成、权限验证等。自定义SPI扩展的步骤一般如下:1.实现自定义的SPI接口(例如,分布式主键生成器接口)。2.在项目的`resources/META-INF/services`目录下创建以SPI接口全限定名命名的文件,并在文件中写入实现类的全限定名。3.将项目打包成jar,并将此jar放入ShardingSphere-Proxy的`ext-lib`目录下(或者通过其他类加载方式加载)。4.修改ShardingSphere-Proxy的配置文件(通常是`server.yaml`或`config-xxx.yaml`)来启用自定义的SPI实现。但是,需要注意的是,ShardingSphereProxy的配置文件分为服务器配置(server.yaml)和规则配置(config-xxx.yaml)。自定义SPI通常需要在规则配置中指定使用自定义的实现。下面我们以自定义分布式主键生成器(ShardingSphere的KeyGenerateAlgorithm)为例,说明整个流程。步骤1:实现KeyGenerateAlgorithm接口例如,我们实现一个简单的自定义主键生成器,生成连续递增的长整型ID。步骤2:创建SPI配置文件在`resources/META-INF/services`目录下创建文件`org.apache.shardingsphere.keygen.core.algorithm.KeyGenerateAlgorithm`(注意:这是ShardingSphere5.5.2中该接口的全限定名,请根据实际版本确认),并在文件中写入我们实现类的全限定名,例如:`com.example.CustomKeyGenerator`。步骤3:打包并放置jar包将项目构建成jar包,并放到ShardingSphere-Proxy的`ext-lib`目录下。如果没有此目录,可以手动创建,然后重启Proxy。步骤4:在规则配置中指定使用自定义主键生成器在配置数据分片规则时,为表指定主键生成策略,使用我们自定义的主键生成器。例如,在`config-sharding.yaml`中:```rules:-!SHARDINGtables:t_order:actualDataNodes:ds_${0..1}.t_order_${0..1}keyGenerateStrategy:column:order_idkeyGeneratorName:custom_key_generatorkeyGenerators:custom_key_generator:type:CUSTOM#注意,这里如果使用自定义,type必须是CUSTOMprops:#自定义的属性,如果有的话```但是,上面的配置中,我们还需要指定自定义实现的类型名称。在ShardingSphere中,内置了一些主键生成器的类型,如SNOWFLAKE,UUID。对于自定义的,我们需要在配置中指定为CUSTOM,并且在keyGenerator的配置中通过属性指定我们实现类的全限定名(或者使用之前SPI文件中定义的类型名称)?实际上,在ShardingSphere中,自定义的SPI实现会通过SPI文件自动加载,然后我们在配置中使用的就是实现类在SPI文件中定义的类型名称(即实现类的简单名称,或者是在实现类上通过@SingletonSPI和@Algorithm注解指定的名称?)。在ShardingSphere5.5.2中,对于自定义的KeyGenerateAlgorithm,需要在配置中指定`type`为`CUSTOM`,然后通过`props`提供一个`algorithm-class`的属性,值为实现类的全限定名。或者,也可以通过在实现类上使用注解来指定类型名称。具体做法:实现类上添加注解:```@SingletonSPIpublicfinalclassCustomKeyGeneratorimplementsKeyGenerateAlgorithm{...}```然后在配置文件中,我们可以这样引用:```keyGenerators:custom_key_generator:type:CustomKeyGenerator#这里写实现类的类名(首字母小写也可以?)或者注解中指定的值?实际上,ShardingSphereSPI机制会根据类名(去掉接口的前缀,然后转换为小写,例如:如果实现类名为CustomKeyGenerator,那么类型就是CUSTOM_CUSTOM_KEY_GENERATOR?)并不是这样。最好是在实现类上使用@Algorithm注解指定类型名称。因此,我们通常会在实现类上使用@Algorithm注解:```@Algorithm("CUSTOM_KEY")//这里指定一个类型名称publicfinalclassCustomKeyGeneratorimplementsKeyGenerateAlgorithm{...}```然后在配置中:```keyGenerators:custom_key_generator:type:CUSTOM_KEY#与注解中一致```但是,如果不想使用注解,那么ShardingSphere会使用实现类的类名(首字母小写)作为类型。但是,对于不同的实现,最好还是使用注解明确指定类型名称。因此,我们总结配置自定义主键生成器在规则配置中的写法为:```keyGenerators:custom_key_generator:#自定义的主键生成器的名称,可以任意取,在keyGenerateStrategy中引用此名称type:CUSTOM_KEY#这里写我们在实现类上@Algorithm注解指定的类型名称,或者使用类名(首字母小写)props:anyProperty:value#如果有属性,可以在这里配置```注意:在ShardingSphere5.5.2中,自定义的SPI实现需要在配置文件中指定类型(type),而类型名称要么是通过注解@Algorithm指定的,要么就是类名(小写)。同时,必须将实现打包并放置在ext-lib下。另外,如果自定义的SPI实现需要配置属性,可以在实现类中通过@Properties注解定义属性,然后在配置中的props部分传入。但是,上述步骤是针对KeyGenerateAlgorithm的,其他类型的SPI扩展(如AuditStrategy、AuthorityProvider等)步骤类似,但具体配置的位置和方式可能不同。因此,我们给出一个完整的示例(包括代码和配置):1.自定义主键生成器代码:```javapackagecom.example;importorg.apache.shardingsphere.keygen.core.algorithm.KeyGenerateAlgorithm;importorg.apache.shardingsphere.spi.type.typed.Algorithm;importorg.apache.shardingsphere.spi.type.typed.TypedSPI;importjava.util.Properties;@Algorithm("CUSTOM_KEY")//指定类型名称publicfinalclassCustomKeyGeneratorimplementsKeyGenerateAlgorithm{privatePropertiesproperties;@Overridepublicvoidinit(Propertiesproperties){this.properties=properties;}@OverridepublicComparable<?>generateKey(){//这里实现你的主键生成逻辑,返回一个Comparable类型的值//例如,我们简单返回一个自增的long值(实际应用中需要分布式唯一)returnSystem.currentTimeMillis();}@OverridepublicPropertiesgetProps(){returnthis.properties;}@OverridepublicStringgetType(){return"CUSTOM_KEY";//必须与@Algorithm指定的值一致}}```2.在`resources/META-INF/services`目录下创建文件:`org.apache.shardingsphere.keygen.core.algorithm.KeyGenerateAlgorithm`,内容为:```com.example.CustomKeyGenerator```3.打包成jar,例如`custom-sharding-spi.jar`,放入ShardingSphere-Proxy的`ext-lib`目录。4.修改ShardingSphere-Proxy的配置文件`config-sharding.yaml`,在规则部分配置:```rules:-!SHARDINGtables:t_order:actualDataNodes:ds_${0..1}.t_order_${0..1}keyGenerateStrategy:column:order_idkeyGeneratorName:custom_key_generatorkeyGenerators:custom_key_generator:type:CUSTOM_KEY#这里与实现类中@Algorithm注解指定的值一致#如果需要传递属性,可以在props中配置,然后在实现类的init方法中获取props:someProperty:value```5.重启ShardingSphere-Proxy。注意:如果是其他类型的SPI扩展,比如权限验证,需要实现`org.apache.shardingsphere.authority.spi.AuthorityProvider`接口,并在配置文件中配置(在`server.yaml`的权限部分)使用自定义的权限提供者。另外,ShardingSphereProxy的server.yaml中也可以配置权限。例如:```rules:-!AUTHORITYusers:-root@%:root-sharding@:shardingprovider:type:CUSTOM#使用自定义的权限提供者props:#自定义的属性class:com.example.CustomAuthorityProvider```或者,对于自定义的权限提供者,我们同样可以通过SPI机制实现,然后在配置中指定类型(通过@Algorithm注解指定的类型名称)即可。总结:自定义SPI扩展的基本步骤:1.实现SPI接口。2.在META-INF/services下创建SPI配置文件,写入实现类全名。3.打包成jar,放入Proxy的ext-lib目录。4.配置文件中(可能是server.yaml或者rules中的配置)指定使用自定义的实现,通过type指定我们注册的类型名称(通过@Algorithm注解指定)。注意:ShardingSphere的SPI接口分为TypedSPI和SingletonSPI,我们通常使用@SingletonSPI和@Algorithm注解来定义单例的SPI实现。由于不同的SPI扩展配置的位置和方式可能不同,需要查阅具体扩展点的文档或接口所在的包。最后,给出一个相关问题列表。</think> ### 配置 Apache ShardingSphere Proxy 的自定义 SPI 扩展 在 Apache ShardingSphere Proxy 5.5.2配置自定义 SPI 扩展,需遵循以下步骤: --- ### **1. 实现 SPI 接口** 以自定义分布式主键生成器 (`KeyGenerateAlgorithm`) 为例: ```java package com.example; import org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator; import java.util.Properties; public class CustomSnowflakeKeyGenerator implements ShardingKeyGenerator { private Properties properties = new Properties(); @Override public Comparable<?> generateKey() { // 自定义主键生成逻辑 return System.currentTimeMillis() << 22 | 1L; } @Override public String getType() { return "CUSTOM_SNOWFLAKE"; // 自定义类型标识 } @Override public Properties getProperties() { return properties; } @Override public void setProperties(Properties props) { this.properties = props; } } ``` --- ### **2. 创建 SPI 配置文件** 在 `resources/META-INF/services` 目录下创建文件: - **文件名**:`org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator` - **文件内容**: ``` com.example.CustomSnowflakeKeyGenerator ``` --- ### **3. 打包 JAR** 将项目打包为 JAR(如 `custom-spi.jar`),确保包含: - SPI 实现类 - `META-INF/services` 配置文件 --- ### **4. 部署到 ShardingSphere Proxy** 将 JAR 放入 Proxy 的 `ext-lib` 目录: ```bash sharding-proxy-5.5.2/ ├── ext-lib/ │ └── custom-spi.jar # 放置自定义 JAR ├── conf/ │ ├── config-sharding.yaml │ └── server.yaml └── bin/start.sh ``` --- ### **5. 修改 Proxy 配置** 在 `config-sharding.yaml` 中启用自定义 SPI: ```yaml rules: - !SHARDING keyGenerators: custom_key: # 自定义主键生成器名称 type: CUSTOM_SNOWFLAKE # 与 getType() 返回值一致 props: worker.id: 123 # 自定义属性(可选) tables: t_order: actualDataNodes: ds_${0..1}.t_order_${0..1} keyGenerateStrategy: column: order_id keyGeneratorName: custom_key # 引用自定义生成器 ``` --- ### **6. 重启 Proxy** ```bash bin/start.sh # 启动或重启 Proxy ``` --- ### **验证配置** 通过 MySQL 客户端插入数据,观察主键是否按自定义逻辑生成: ```sql INSERT INTO t_order (user_id, status) VALUES (101, 'OK'); ``` --- ### **工作原理** 1. **SPI 加载机制** ShardingSphere 通过 Java SPI 在启动时扫描 `META-INF/services` 下的接口实现。 2. **优先级规则** `ext-lib` 中的 JAR 优先级高于内置实现。 3. **动态注入** 配置中的 `type` 需与实现类的 `getType()` 返回值匹配。 --- ### **常见问题排查** - **SPI 未生效** 检查 JAR 是否在 `ext-lib` 目录,且 `META-INF/services` 文件路径正确。 - **类型不匹配** 确保配置中的 `type` 与代码中 `getType()` 返回值一致。 - **属性传递失败** 在 `props` 中定义的属性需通过 `setProperties()` 方法处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值