当前位置: 首页 > 知识库问答 >
问题:

如何从应用程序的多个实例同时运行相同的spring批处理作业

慕容成文
2023-03-14

我创建了一个Spring批处理作业,它在定义的时间使用调度器执行。我们有同一个应用程序的多个实例,因此相同的作业从多个实例中同时执行。所有应用程序使用相同的数据库。由于那我得到下面的错误

堆栈跟踪:org。springframework。交易TransactionSystemException:无法提交JDBC事务嵌套的异常是org。postgresql。util。PSQLException:错误:由于事务之间的读/写依赖关系,无法序列化访问详细信息:原因代码:在提交尝试期间,在标识为枢轴时取消。提示:如果重试,事务可能会成功。在org。springframework。jdbc。数据源。数据源事务管理器。doCommit(DataSourceTransactionManager.java:335)位于org。springframework。交易支持AbstractPlatformTransactionManager。processCommit(AbstractPlatformTransactionManager.java:743)位于org。springframework。交易支持AbstractPlatformTransactionManager。在org提交(AbstractPlatformTransactionManager.java:711)。springframework。交易拦截器。TransactionSpect支持。commitTransactionAfterReturning(TransactionSpectSupport.java:631)位于org。springframework。交易拦截器。TransactionSpect支持。在org上调用Withintransaction(TransactionSpectSupport.java:385)。springframework。交易拦截器。交易接收器。在org调用(TransactionInterceptor.java:118)。springframework。aop。框架ReflectiveMethodInvocation。在org上继续(ReflectiveMethodInvocation.java:186)。springframework。一批果心存储库。支持AbstractJobRepositoryFactoryBean$1。在org调用(AbstractJobRepositoryFactoryBean.java:181)。springframework。aop。框架ReflectiveMethodInvocation。在org上继续(ReflectiveMethodInvocation.java:186)。springframework。aop。框架JdkDynamicAopProxy。在com上调用(JdkDynamicAopProxy.java:212)。太阳代理$Proxy209。组织上的createJobExecution(未知源)。springframework。一批果心发射支持simplejoblancher。运行(simplejoblancher.java:137)

我用下面的代码说明了我的工作-

JobParameters params = new JobParametersBuilder()
            .addString("JobID", UUID.randomUUID().toString(), true)
            .toJobParameters();
jobLauncher.run(job, params);

并在yaml文件中执行以下配置

batch:
job:
  enabled: false
initialize-schema: always
repository:
  isolationlevelforcreate: ISOLATION_READ_COMMITTED

我添加了监听器来检查任何正在运行的作业是否处于启动状态,如果找到任何正在运行的作业,则当前作业将停止

public class SingleInstanceListener implements JobExecutionListener {
@Autowired
private JobExplorer explorer;

@Override
public void beforeJob(JobExecution jobExecution) {
    String jobName = jobExecution.getJobInstance().getJobName();
    Set<JobExecution> executions = explorer.findRunningJobExecutions(jobName);
    if(executions.size() > 1) {
        jobExecution.stop();
    }
}

@Override
public void afterJob(JobExecution jobExecution) {

}

}

但我仍然得到上述错误。如果只有一个应用程序实例,那么作业运行正常。有没有办法同时从多个应用程序实例运行相同的作业,或者只允许从任何一个应用程序运行一个作业。

共有1个答案

南门野
2023-03-14

隔离级别没有像您期望的那样考虑到该属性。要自定义隔离级别,需要通过BatchConfigurer提供JobRepository。下面是一个简单的例子:

@Configuration
@EnableBatchProcessing
public class MyJobConfig extends BasicBatchConfigurer {

    @Override
    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean();
        repositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
        // set other properties on the factory bean
        repositoryFactoryBean.afterPropertiesSet();
        return repositoryFactoryBean.getObject();
    }
}

在这里的留档中解释了这一点:JobRepository的事务配置。

注意:BasicBatchConfigurer来自Spring Boot。如果在没有Spring Boot的情况下使用Spring批处理,则可以扩展DefaultBatchConfigurer

 类似资料:
  • 使用spring batch/spring boot,是否可以在每个线程中使用不同的多次启动具有读取器、处理器和写入器的spring batch作业? 我的用例: 我有许多不同的文件夹,我需要观看。如果新文件进入一个文件夹,我需要调用该作业,并在作业处理期间锁定该文件夹。 这可能发生在不同数量的文件夹中,这就是为什么我需要一个spring批处理作业的多个实例,但每次使用不同的。 每个文件夹一个作业

  • 这就是我现有系统的工作方式。 我使用spring批处理编写了批处理,它将消息异步写入队列。Writer一旦向queue发送了一定数量的消息,就开始监听LINKED_BLOCKING_QUEUE中相同数量的消息。 我有spring amqp监听器,它使用并处理消息。一旦处理完毕,使用者就会在回复队列中回复。有侦听器侦听应答队列,以检查消息是否被成功处理。应答侦听器检索响应并将其添加到LINKED_B

  • 我配置了一个spring批处理作业,它在spring WebService中运行。这项工作有几个步骤。我已经在不同的tomcats中部署了这个webservice的两个实例(但两个实例都使用相同的mysql数据库)。 我希望用不同的参数在两个tomcats中同时运行spring批处理作业(每个tomcats中一个)。我没有使用分区,每个作业的参数是完全不同的。 我开始工作在一个汤姆猫和一切看起来很

  • 我们的要求是同时写多个文件。我们正在使用spring批处理来编写文件,并且我们正在从不同的线程中启动spring批处理。每个线程都有自己的应用程序上下文。因此我们可以确保单例bean不会跨多个线程共享。下面是我的代码片段。 这就是我们调用spring批处理的方式。 ThreadPoolExecutor TPE=new ThreadPoolExecutor(10,10,1000000,TimeUni

  • 到目前为止,我正在运行spring批处理,只有一个作业。现在我想运行多个不同的作业,这意味着不同的功能。在我的配置文件中,我配置了两个具有不同id和不同名称的作业。现在我得负责这些工作。你能告诉我怎么跑吗。在这里,我的疑问是在我的java类中,我已经为运行批处理编写了这段代码。 对于其他作业,如何调用jobLauncher的run方法。 我的配置文件是

  • 我在BatchScheduler中有多个计划作业,它在特定时间运行。简单的内置JobLauncher,这是同步的。在自然界中最初使用。现在,我想并行运行这些作业,这样没有作业可以等待其他作业完成。 我在不同的作业上尝试过@Async注释,但都不起作用。 然后,我尝试设置joblauncher.settaskexecutor(新的SimpleAsyncTaskExecutor())。但这并不奏效。

  • 在表中,默认情况下传递和作业参数。当我使用REST endpoint launcher方法触发作业时,我没有看到这些参数在默认情况下被传递。 并且在每个作业运行中传递这两个参数的相同值。和。正如所料,它给出了以下异常。 我的问题是: 当我使用命令行触发作业时,为什么默认情况下传递此和作业参数? ,为什么每次运行作业时传递的两个参数的值都是一样的?即使我正在使用 方法是如何创建差异的?

  • 有人能想出一个变通方法来解决osascript索引按名称瓶颈引用同一应用程序的多个实例吗? 如果我们获得两个进程id-一个用于同一个应用程序的两个不同实例,osascript返回相同的实例来交换其中一个pid-就像它首先将pid映射到一个应用程序名称,然后检索具有该名称的第一个应用程序进程一样。 例如,启动两个不同的VLC实例。应用程序,播放两个不同的视频文件,类似: 然后获取两个单独的应用程序进