在多个数据库上并行运行 Spring Batch
Posted
技术标签:
【中文标题】在多个数据库上并行运行 Spring Batch【英文标题】:Running Spring batch on multiple databases in parallel 【发布时间】:2017-11-10 02:38:30 【问题描述】:我使用 Spring boot 创建了一个 Spring 批处理应用程序,并且我有一个包含 9 个步骤的 Job
。这些步骤使用DataSource
,我在配置文件中创建了它的bean,如下所示:
@Configuration
public class DatabaseConfig
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
@Primary
public DataSource dataSource()
return DataSourceBuilder.create().build();
这个DataSource
正在使用application.yml
文件中声明的属性:
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_01?zeroDateTimeBehavior=convertToNull
username: xxxx
password: ****
到目前为止,一切都按预期工作。
我想要做的是,我在第 5 个数据库 (db_settings) 中参数化了 4 个数据库,我使用 SQL 查询来选择这些数据库。此查询将返回 4 个数据库及其用户名和密码,如下所示:
+--------+-----------------------------------+-----------------+-----------------+
| id | url | username_db | password_db |
+--------+-----------------------------------+-----------------+-----------------+
| 243 | jdbc:mysql://localhost:3306/db_01 | xxxx | **** |
| 244 | jdbc:mysql://localhost:3306/db_02 | xxxx | **** |
| 245 | jdbc:mysql://localhost:3306/db_03 | xxxx | **** |
| 247 | jdbc:mysql://localhost:3306/db_04 | xxxx | **** |
+--------+-----------------------------------+-----------------+-----------------+
因此,我不想使用“application.yml”中声明的数据库运行这些步骤,而是想在所有 4 个数据库上运行它们。 并且考虑到处理的量,有必要能够在这些数据库上并行启动批处理。
有人知道如何实现吗?
【问题讨论】:
我现在没有时间详细回答,但您可以结合两个简洁的功能来实现这一点:来自 Spring Batch 的分区作业 分区键是数据源 id 243、244 等) 和 Spring JDBC 中的 AbstractRoutingDataSource(它将从使用分区键初始化的作业参数中动态选择正确的数据源) @KeatsPeeks 很抱歉,我什么也得不到,如果您添加更多详细信息或代码示例,我将不胜感激。 【参考方案1】:赏金在哪里? :-)
感谢 KeatsPeeks,AbstractRoutingDataSource
是解决方案的良好开端,这里是这部分的 good tutorial。
主要有以下重要部分:
-
定义查找代码
public class MyRoutingDataSource extends AbstractRoutingDataSource
@Override
protected Object determineCurrentLookupKey()
String language = LocaleContextHolder.getLocale().getLanguage();
System.out.println("Language obtained: "+ language);
return language;
注册多个数据源
<bean id="abstractDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="$jdbc.driverClassName"
p:username="$jdbc.username"
p:password="$jdbc.password" />
<bean id="concreteDataSourceOne"
parent="abstractDataSource"
p:url="$jdbc.databaseurlOne"/>
<bean id="concreteDataSourceTwo"
parent="abstractDataSource"
p:url="$jdbc.databaseurlTwo"/>
那么之后,问题就变成了:
如何在spring启动时加载datasource config属性,并使用数据库中的config属性配置对应的dataSource
。
如何在spring批处理中使用多个dataSource
其实我google的时候,好像这是最常见的情况,google给出的建议搜索词——“spring batch 多数据源”,文章很多,所以我选择答案在
如何定义基于spring批处理作业的查找代码(步骤)
通常这应该是一个业务点,您需要定义查找策略并可以注入com.example.demo.datasource.CustomRoutingDataSource#determineCurrentLookupKey
以路由到专用数据源。
限制
真正有趣的是它实际上支持多个dataSource
,但数据库设置确实不能存储在数据库中。原因是它会得到循环依赖问题:
The dependencies of some of the beans in the application context form a cycle:
batchConfiguration (field private org.springframework.batch.core.configuration.annotation.JobBuilderFactory com.example.demo.batch.BatchConfiguration.jobs)
↓
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration (field private java.util.Collection org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.dataSources)
┌─────┐
| routingDataSource defined in class path resource [com/example/demo/datasource/DataSourceConfiguration.class]
↑ ↓
| targetDataSources defined in class path resource [com/example/demo/datasource/DataSourceConfiguration.class]
↑ ↓
| myBatchConfigurer (field private java.util.Collection org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.dataSources)
└─────┘
显然解决方案是打破dataSource
和routingDataSource
之间的依赖关系
dataSource
另见
https://scattercode.co.uk/2013/11/18/spring-data-multiple-databases/ https://numberformat.wordpress.com/2013/12/27/hello-world-with-spring-batch-3-0-x-with-pure-annotations/
http://spring.io/guides/gs/batch-processing/
How to java-configure separate datasources for spring batch data and business data? Should I even do it?
Github 获取验证码。
【讨论】:
以上是关于在多个数据库上并行运行 Spring Batch的主要内容,如果未能解决你的问题,请参考以下文章
Spring Batch - 如何使用一个读取其他步骤的作者的并行步骤?