问题
Currently we are migrating a batch job from java to spring batch.This batch job gets its input from database and web service. We need to run this job in four servers for an increased performance as this job is handling huge data.
Is the above scenario is achievable through remote partitioning in spring batch?
I went through remote partitioning documents but its difficult to understand and I did n't find any solid examples in remote partitioning.
Please help me on this.
回答1:
Yes, what you are describing will work with remote partitioning. I do a talk on the scalability options in Spring Batch that you can view here: https://www.youtube.com/watch?v=CYTj5YT7CZU
The code examples for running it can be found here: https://github.com/mminella/Spring-Batch-Talk-2.0
回答2:
I would like to share remote partitioning example. you can find all sources here
Master application:
batch config:
@Configuration
@EnableBatchProcessing
@EnableBatchIntegration
@Import(value = {BrokerConfiguration.class})
public class MasterConfiguration {
private static final int GRID_SIZE = 3;
private final JobBuilderFactory jobBuilderFactory;
private final RemotePartitioningMasterStepBuilderFactory masterStepBuilderFactory;
public MasterConfiguration(JobBuilderFactory jobBuilderFactory,
RemotePartitioningMasterStepBuilderFactory masterStepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.masterStepBuilderFactory = masterStepBuilderFactory;
}
/*
* Configure outbound flow (requests going to workers)
*/
@Bean
public DirectChannel requests() {
return new DirectChannel();
}
@Bean
public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) {
return IntegrationFlows
.from(requests())
.handle(Jms.outboundAdapter(connectionFactory).destination("requests"))
.get();
}
/*
* Configure inbound flow (replies coming from workers)
*/
@Bean
public DirectChannel replies() {
return new DirectChannel();
}
@Bean
public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) {
return IntegrationFlows
.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("replies"))
.channel(replies())
.get();
}
/*
* Configure the master step
*/
@Bean
public Step masterStep() {
return this.masterStepBuilderFactory.get("masterStep")
.partitioner("workerStep", new BasicPartitioner())
.gridSize(GRID_SIZE)
.outputChannel(requests())
.inputChannel(replies())
.build();
}
@Bean
public Job remotePartitioningJob() {
return this.jobBuilderFactory.get("remotePartitioningJobMy")
.incrementer(new RunIdIncrementer())
.start(masterStep())
.build();
}
}
partitioner:
public class BasicPartitioner extends SimplePartitioner {
private static final String PARTITION_KEY = "partition";
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
Map<String, ExecutionContext> partitions = super.partition(gridSize);
int i = 0;
for (ExecutionContext context : partitions.values()) {
context.put(PARTITION_KEY, PARTITION_KEY + (i++));
}
return partitions;
}
}
broker config:
@Configuration
@PropertySource("classpath:remote-partitioning.properties")
public class BrokerConfiguration {
@Value("${broker.url}")
private String brokerUrl;
@Bean
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setBrokerURL(this.brokerUrl);
connectionFactory.setTrustAllPackages(true);
return connectionFactory;
}
}
starter:
@EnableBatchProcessing
@SpringBootApplication
@Import({BasicPartitioner.class, BrokerConfiguration.class})
public class MasterApplication {
@Value("${broker.url}")
private String brokerUrl;
public static void main(String[] args) {
SpringApplication.run(MasterApplication.class, args);
}
@PostConstruct
public void init() throws Exception {
BrokerService broker = new BrokerService();
broker.addConnector(brokerUrl);
broker.start();
}
}
Slave application:
config:
@Configuration
@EnableBatchProcessing
@EnableBatchIntegration
@Import(value = {BrokerConfiguration.class})
public class WorkerConfiguration {
private final RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory;
public WorkerConfiguration(RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory) {
this.workerStepBuilderFactory = workerStepBuilderFactory;
}
/*
* Configure inbound flow (requests coming from the master)
*/
@Bean
public DirectChannel requests() {
return new DirectChannel();
}
@Bean
public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) {
return IntegrationFlows
.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests"))
.channel(requests())
.get();
}
/*
* Configure outbound flow (replies going to the master)
*/
@Bean
public DirectChannel replies() {
return new DirectChannel();
}
@Bean
public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) {
return IntegrationFlows
.from(replies())
.handle(Jms.outboundAdapter(connectionFactory).destination("replies"))
.get();
}
/*
* Configure the worker step
*/
@Bean
public Step workerStep() {
return this.workerStepBuilderFactory.get("workerStep")
.inputChannel(requests())
.outputChannel(replies())
.tasklet(tasklet(null))
.build();
}
@Bean
@StepScope
public Tasklet tasklet(@Value("#{stepExecutionContext['partition']}") String partition) {
return (contribution, chunkContext) -> {
System.out.println("processing " + partition);
return RepeatStatus.FINISHED;
};
}
}
starter:
@EnableBatchProcessing
@SpringBootApplication
@Import({BrokerConfiguration.class})
public class WorkerApplication {
public static void main(String[] args) {
SpringApplication.run(WorkerApplication.class, args);
}
}
来源:https://stackoverflow.com/questions/21154381/spring-batch-remote-partitioning