Spring Boot:可扩展的任务,如线程 – 如何实现?

huangapple go评论67阅读模式
英文:

Spring Boot: Scalable tasks like Threads - how to do?

问题

我正在学习Spring Boot并希望执行任务。

假设我的应用程序了解不同的客户端。对于任何客户端,我希望执行定期操作(例如,每分钟检查一次邮件帐户)。客户端的数量在应用程序执行过程中可能会变化(例如,从一个随着时间增长或缩小的DB表中)。

在“正常”的程序中,我会为每个客户端启动一个线程,在无限循环中进行邮件处理并设置延迟。在执行过程中,线程的数量会变化。

如何在Spring Boot中执行这样的任务?
我希望在框架之外有一些工具来完成这个任务。

我知道使用@Scheduled注解的组件,但这是静态的,不能动态控制(据我所知)。

英文:

I am starting with Spring Boot and want to execute tasks.

Lets say my application knows different clients. For any client I like to do a periodic action (e.g. check a mail-account every minute). The number of clients may vary during the execution of the application (e.g. out of a DB table that grows or shrinks in time).

In a "normal" program I would start a thread for any client that does the mail-handling inside a endless loop with a delay. During execution the number of threads would vary.

How can I do such tasks with Spring Boot?
I would expect some tools beside threads out of the framework.

I know Components with @Scheduled but that is static and not dynamically to control (as far I know).

答案1

得分: 1

你可以使用Spring的TaskScheduler。假设你有一个客户处理组件负责为每个客户端调度和停止任务。

你可以注入TaskScheduler:

@Autowired
private TaskScheduler taskScheduler;

然后在应用程序需要时为特定客户端启动任务:

CronTrigger cronTrigger = new CronTrigger(yourCronExpression);
ScheduledFuture<?> jobHandler = this.taskScheduler.schedule(new Runnable() {
    @Override
    public void run() {
        // 你可以在这里放置你的代码,或者静态地获取一个组件的实例来调用
    }
}, cronTrigger);

最后,你可以将返回的jobHandler根据客户端ID放入一个映射中,如果以后需要停止计划任务,可以使用它:

this.yourHandlersMap.get(clientId).cancel(false);
英文:

You can use the spring TaskScheduler. Let's say you have a client handler component responsible for scheduling and stopping jobs for each client.

You can inject the TaskScheduler:

@Autowired
private TaskScheduler taskScheduler;

Then start a job for a specific client when your application requires:

CronTrigger cronTrigger = new CronTrigger(yourCronExpression);
ScheduledFuture&lt;?&gt; jobHandler = this.taskScheduler.schedule(new Runnable() {
	@Override
	public void run() {
		// You can put your code here or get statically an instance of a component to invoke
	}
}, cronTrigger);

Finally, you can put the returned jobHandler in a map by client ID, and use it if you have to stop a scheduled task later:

this.yourHandlersMap.get(clientId).cancel(false);

答案2

得分: 0

有几种方法可以处理这个问题,我想这取决于您是否能够在客户计划内完成所有工作。

如果可以的话,您可以简单地循环遍历所有客户并检查他们的邮件。如果不能在您的计划操作中完成工作,而是计算需要完成的工作并将其放入队列中,每个客户可能会有1条消息,或者您可能会将一些客户分批处理,然后会有工作者从此队列中读取工作。

如果您的队列开始积压,工作的到来速度快于您的处理速度,那么请调整您的计划以减少频率,或者增加工作者。

英文:

There is a few ways to go about this, I guess to it depends on whether you can do all the work within the Schedule for clients or not

If you can you can simply loop through all the clients checking their mail. If you cant in your Scheduled action you don't do the work, but instead calculate the work which is needing to be done, and put that work in a queue, there could be 1 message per client, or you might batch some clients up, and then there would be workers which read work from this queue.

If your queue starts to bank up, and work is coming in quicker than you can do it, then adjust your schedule to be less frequent, or add workers.

huangapple
  • 本文由 发表于 2020年9月29日 00:12:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/64105849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定