Springboot整合shardingsphere和druid进⾏读写分离最近在使⽤springboot整合shardingsphere和druid实现mysql数据库读写分离时遇到了⼀些问题,特此记录⼀下。
依赖版本
Springboot 2.1.6.RElEASE
shardingsphere 4.1.1
druid 1.1.23
需要的依赖如下:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
yml⽂件配置
datasource配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: sql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: root
druid:
async-init: true
keep-alive: true
filters: stat,wall,logback  # 必须配置项,否则sql监控页⾯没有内容
initial-size: 5
max-active: 50
min-idle: 5
max-wait: 6000
validation-query: SELECT 'x'
test-on-borrow: false
test-on-return: false
test-while-idle: true
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
remove-abandoned: false
log-abandoned: true
filter:
stat:
enabled: true
log-slow-sql: true
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
stat-view-servlet:
enabled: true # 控制是否开启监控页⾯
url-pattern: /druid/*
reset-enable: false
# ip⽩名单,默认是127.0.0.1,为空时表⽰所有的ip都可以访问,如果这⾥允许所有ip访问必须配置为空,否则只能127.0.0.1访问
allow:
# ip⿊名单,同理⽩名单
deny:
login-username: druid  # 监控页⾯登陆⽤户名
login-password: druid  # 监控页⾯登陆密码
读写分离的sharding配置
spring:
shardingsphere:
enabled: true # 是否启⽤sharding,不启⽤时使⽤datasource配置的数据源
datasource:
names: master,slave0 # 节点名称,多个时使⽤逗号隔开
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: sql.cj.jdbc.Driver
url: jdbc:mysql://10.18.121.222:3306/spider?characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai        username: root
password: 123456
# 以下为druid配置,可以共⽤datasource中的druid配置,需要覆盖时再重新配置
filters: stat,wall,logback
initial-size: 2
max-active: 45
min-idle: 6
slave0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: sql.cj.jdbc.Driver
url: jdbc:mysql://10.18.121.222:3307/spider?characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: 123456
# 以下为druid配置,可以共⽤datasource中的druid配置,需要覆盖时再重新配置
filters: stat,wall,logback
initial-size: 3
max-active: 20
min-idle: 8
masterslave:
name: ms
master-data-source-name: master
slave-data-source-names: slave0
props:
sql:
show: true
注意:
sharding数据源中的druid配置项基本可以使⽤spring.datasource.druid中的配置项,但是在实际使⽤过程中发现,filters: stat,wall,logback这项配置必须重新给各个数据源配置,不然sql监控页⾯没有任何内容展⽰。
遇到的问题
通过以上两个步骤的配置,启动没有任何业务类的springboot项⽬,成功启动,并且访问druid监控页⾯也正常,在满怀激动的往正式项⽬中迁移后,发现项⽬启动失败,出现了下图所⽰的异常:
这是什么⿁?以为配置出错了,赶紧⼀顿检查检查配置,发现没有任何问题,在多次尝试⽆果后将配置还原发现⼜可以正常启动从⽽基本确定是sharding和druid的配置导致了项⽬启动失败。
从sharding官⽹的FAQ中发现如下解释:
根据官⽹的解释以及从⽹上查的⼀些资料来看,解决⽅案有两个:
去掉druid-spring-boot-starter,直接使⽤druid-xxx.jar来替代,这就不会出现两个数据源冲突的问题
仍然使⽤druid-spring-boot-starter,但是在springboot的启动类上exclude掉DruidDataSourceAutoConfigure这个类,忽略druid连接池的默认数据源配置
(@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class}))
经过⼀番尝试,以上两种⽅案都可以解决启动报错的问题,但是使⽤上述两种⽅案,即使配置了打开druid监控页⾯的配置,访问监控页⾯时仍然是404,我的需求是要能监控数据库的,因此上述两种⽅案都不可⾏。
⼜要有监控页⾯,⼜要项⽬正常启动,⼀时陷⼊了僵局,后来在查资料的过程中,发现可以通过⼿动创建数据源配置,并且将其指定为默认数据源就可以解决该问题,经过查到的资料以及公司⼤佬的⽀持,添加如下所⽰的配置类:
@Configuration
@EnableConfigurationProperties(JpaProperties.class)
public class DataSourceConfiguration {
private final JpaProperties jpaProperties;
private final Environment environment;
public DataSourceConfiguration(JpaProperties jpaProperties, Environment environment) {
this.jpaProperties = jpaProperties;
}
@Primary
@Bean
public DataSource dataSource() {
String prefix = "spring.shardingsphere.datasource.";
String each = DataSourceNames(prefix).get(0);
try {
DataSource(prefix, each);
} catch (final ReflectiveOperationException ex) {
throw new ShardingSphereException("Can't find datasource type!", ex);
}
}
@Primary
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPersistenceUnitName("default");
factory.setPackagesToScan("com.lzm.*");
factory.setDataSource(this.dataSource());
factory.setJpaPropertyMap(Properties());
factory.afterPropertiesSet();
Object();
}
@Bean
@Primary
public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
ateSharedEntityManager(entityManagerFactory);
}
@Primary
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
druid连接池配置详解txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
private List<String> getDataSourceNames(final String prefix) {
StandardEnvironment standardEnv = (StandardEnvironment) vironment;
standardEnv.setIgnoreUnresolvableNestedPlaceholders(true);
return null == Property(prefix + "name")
new Property(prefix + "names")).splitAndEvaluate()
: Collections.Property(prefix + "name"));
}
@SuppressWarnings("unchecked")
private DataSource getDataSource(final String prefix, final String dataSourceName) throws ReflectiveOperationException {
Map dataSourceProps = PropertyUtil.vironment, prefix + im(), Map.class);
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
DataSource result = ("type").toString(), dataSourceProps);
<("type").toString())
.ifPresent(dataSourcePropertiesSetter -> dataSourcePropertiesSetter.vironment, prefix, dataSourceName, result));
return result;
}
}
以上打码中根据sharding的配置⼿动创建数据源DataSource以及EntityManagerFactory等Bean,并且设置为默认加载的bean类型(@Primary),添加以上配置类后,重新启动项⽬,项⽬正常启动⽽且druid的监控页⾯也可以正常访问,此问题得到完美解决。具体源码可以参考
参考⽂档
1.
2.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。