如果开始新运行同一作业,则正在运行的作业将停止-Spring Batch [英] Running job stops if start new running the same job - Spring Batch

查看:72
本文介绍了如果开始新运行同一作业,则正在运行的作业将停止-Spring Batch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我有点困惑,因为当通过HTTP请求开始执行Spring Batch作业时,如果我收到另一个HTTP请求以启动相同的作业,但是在执行作业时使用不同的参数,则该作业正在执行执行停止未完成,并且开始处理新作业.

上下文

我已经开发了一个API REST来加载和处理Excel文件的内容.该Web服务公开了两个端点,一个端点用于加载,验证和存储数据库中Excel文件的内容,另一个端点用于开始处理数据库中存储的记录.

它如何工作

  • POST/api/excel/upload该端点接收Excel文件.收到请求后,将为每个文件分配一个唯一的标识符,并验证其内容.如果内容正确,则会将其插入临时表中等待处理.

  • GET/api/Excel/process?id = x该端点接收要处理的文件的标识符.收到请求后,将启动Spring Batch作业来处理临时表中的记录.

某些代码

  • 控制器

  @PostMapping(产生= {APPLICATION_JSON_VALUE})公共ResponseEntity< Page< ExcelLoad>>post(@RequestParam("file")MultipartFile multipartFile){返回super.getResponse().returnPage(service.upload(multipartFile));}@GetMapping(value ="/process",产生= APPLICATION_JSON_VALUE)公共DeferredResult< ResponseEntity< Void>>get(@RequestParam("id")整数idCarga){DeferredResult< ResponseEntity< Void>>响应=新的DeferredResult(1000L);response.onTimeout(()-> response.setResult(super.getResponse().returnVoid()));ForkJoinPool.commonPool().submit(()-> service.startJob(idCarga));返回响应;} 

我使用DeferredResult在收到请求后向客户端发送响应,而无需等待作业完成

  • 服务

  public void startJob(int idCarga){JobParameters参数=新的JobParametersBuilder().addString("mainJob",String.valueOf(System.currentTimeMillis())).addString("idCarga",String.valueOf(idCarga)).toJobParameters();尝试{jobLauncher.run(job,params);}捕获(JobExecutionException e){log.error(-错误:{}",e.getMessage());}} 

  • 批次

  @Beanpublic Step mainStep(ReaderImpl读取器,ProcessorImpl处理器,WriterImpl写入器){返回stepBuilderFactory.get("step").<列表< ExcelLoad> ;,发票> chunk(10).reader(阅读器).processor(处理器).writer(作家).faultTolerant().skipPolicy(new ExceptionSkipPolicy()).listener(stepSkipListener).建造();}@豆角,扁豆public Job mainJob(Step mainStep){返回jobBuilderFactory.get("mainJob").listener(mainJobExecutionListener).incrementer(新的RunIdIncrementer()).start(mainStep).建造();} 

执行一些测试,我观察到以下行为:

  1. 如果我请求端点/进程在不同时间处理每个文件:在这种情况下,将处理临时表中存储的所有记录:

    • 记录已处理的文件1:3606(预期为3606).
    • 记录已处理的文件2:1776(预期为1776).
  2. 如果我向端点/进程请求第一个处理文件1,并且在完成之前,我又请求处理文件2:在这种情况下,并非存储在临时表中的所有记录都被处理:/p>

    • 记录已处理的文件1:1080(预期为3606)
    • 记录已处理的文件2:1774(预计1776年)

解决方案

JobLauncher 不会停止作业执行,只会启动它们.Spring Batch提供的默认作业启动器是 SimpleJobLauncher ,它将作业启动委托给 TaskExecutor .现在,根据您使用的任务执行器实现以及将其配置为启动并发任务的方式,您可以看到不同的行为.例如,当您启动一个新的作业执行并将新任务提交给任务执行者时,如果所有工作人员都忙,任务执行者可以决定拒绝此提交,或者将其置于等待队列中,或者停止另一个任务并提交新的那一个.这些策略取决于几个参数( TaskExecutor 实现,在幕后使用的队列类型, RejectedExecutionHandler 实现等).

在您的情况下,您似乎正在使用以下内容:

  ForkJoinPool.commonPool().submit(()-> service.startJob(idCarga)); 

因此,您需要检查该池在处理新任务提交方面的行为(我想这是停止您的工作的原因,但您需要确认这一点).就是说,我不明白你为什么需要这个.如果您的要求如下:

我使用DeferredResult在收到请求后将响应发送给客户端,而无需等待作业完成

然后,您可以在作业启动器中使用异步任务执行器实现(例如 ThreadPoolTask​​Executor ),请参见 解决方案

The JobLauncher does not stop job executions, it only launches them. The default job launcher provided by Spring Batch is the SimpleJobLauncher which delegates job launching to a TaskExecutor. Now depending on the task executor implementation you use and how it is configured to launch concurrent tasks, you can see different behaviours. For example, when you launch a new job execution and a new task is submitted to the task executor, the task executor can decide to reject this submission if all workers are busy, or put it in a waiting queue, or stop another task and submit the new one. Those strategies depend on several parameters (TaskExecutor implementation, the type of the queue used behind the scene, the RejectedExecutionHandler implementation, etc) .

In your case, you seem to be using the following:

ForkJoinPool.commonPool().submit(() -> service.startJob(idCarga));

So you need to check the behaviour of this pool with regard to how it handles new task submissions (I guess this is what is stopping your jobs, but you need to confirm that). That said, I don't see why you need this. If your requirement is the following:

I use DeferredResult to send a response to the client after receiving the request without waiting for the job to finish

Then you can use an asynchronous task executor implementation (like the ThreadPoolTaskExecutor) in your job launcher, see Running Jobs from within a Web Container.

这篇关于如果开始新运行同一作业,则正在运行的作业将停止-Spring Batch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆