如何在某些时间窗口中运行方法

发布于 2025-02-11 10:09:43 字数 181 浏览 1 评论 0 原文

我有一个微服务会收到一条消息,类似的东西:

["00:12", "12:20", "15:40"]

是否有任何开箱即用的解决方案可以允许每天给定时间运行的方法? 使用Spring的Cron不涉及更改运行时的时间。我需要使用一个更灵活的选项(更改运行时,多次启动)

谢谢!

I have a microservice that will receive a message, something like this:

["00:12", "12:20", "15:40"]

Are there any out-of-the-box solutions to allow methods to run at a given time each day?
Using cron from Spring does not involve changing the time at runtime. I need to use a more flexible option (change in runtime, multiple launch starts)

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

亽野灬性zι浪 2025-02-18 10:09:43

Spring具有 @scheduled 注释。有几种配置它的方法,一种方法是像Unix Cron作业一样配置它。

例如:

@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
 
    long now = System.currentTimeMillis() / 1000;
    System.out.println(
      "schedule tasks using cron jobs - " + now);
}

此处的任务计划在每个月的15天在上午10:15执行。

但是,也有一种方法可以在运行时动态配置延迟或速率,例如这样(取自baeldung.com):

@Configuration
@EnableScheduling
public class DynamicSchedulingConfig implements SchedulingConfigurer {

    @Autowired
    private TickService tickService;

    @Bean
    public Executor taskExecutor() {
        return Executors.newSingleThreadScheduledExecutor();
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
        taskRegistrar.addTriggerTask(
          new Runnable() {
              @Override
              public void run() {
                  tickService.tick();
              }
          },
          new Trigger() {
              @Override
              public Date nextExecutionTime(TriggerContext context) {
                  Optional<Date> lastCompletionTime =
                    Optional.ofNullable(context.lastCompletionTime());
                  Instant nextExecutionTime =
                    lastCompletionTime.orElseGet(Date::new).toInstant()
                      .plusMillis(tickService.getDelay());
                  return Date.from(nextExecutionTime);
              }
          }
        );
    }

}

即时NextExecution Time = ... 可以用自己的逻辑代替设置下一个执行时间,就像从数组中解析时间一样。

看一下有关它的贝尔登教程: https://wwww.baeldung-com/spring-spring-scheduled -tasks

也请在这里查看cron符号: https://www.netiq.com/documentation/cloud-manager-2-5/ncm-reference/data/bexyssf.html

Spring has the @Scheduled annotation. There a several ways to configure it, one way is to configure it like unix cron job.

For example like this:

@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
 
    long now = System.currentTimeMillis() / 1000;
    System.out.println(
      "schedule tasks using cron jobs - " + now);
}

The task here is scheduled to be executed at 10:15 AM on the 15th day of every month.

But there a also ways to configure the delay or rate dynamically at Runtime, for example like this (taken from baeldung.com):

@Configuration
@EnableScheduling
public class DynamicSchedulingConfig implements SchedulingConfigurer {

    @Autowired
    private TickService tickService;

    @Bean
    public Executor taskExecutor() {
        return Executors.newSingleThreadScheduledExecutor();
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
        taskRegistrar.addTriggerTask(
          new Runnable() {
              @Override
              public void run() {
                  tickService.tick();
              }
          },
          new Trigger() {
              @Override
              public Date nextExecutionTime(TriggerContext context) {
                  Optional<Date> lastCompletionTime =
                    Optional.ofNullable(context.lastCompletionTime());
                  Instant nextExecutionTime =
                    lastCompletionTime.orElseGet(Date::new).toInstant()
                      .plusMillis(tickService.getDelay());
                  return Date.from(nextExecutionTime);
              }
          }
        );
    }

}

The line Instant nextExecutionTime = ... could be replaced with your own logic for setting the next execution time, like parsing the times from your array.

Take look at this baeldung tutorial about it: https://www.baeldung.com/spring-scheduled-tasks

Also take look here for the cron notation: https://www.netiq.com/documentation/cloud-manager-2-5/ncm-reference/data/bexyssf.html

夏日浅笑〃 2025-02-18 10:09:43

最好的解决方案(几乎总是如此)取决于您的基础架构必须工作的上下文。

您可以使用 @scheduled (即),但在集群中表现不佳(通常只有一个节点运行作业)。

我将建议在简单,效率和可靠性之间保持良好平衡的解决方案。稍后,我将讨论它的一些属性。

建议的解决方案:

  1. 使用具有保证原子性的有序列表(消息队列,redis排序列表,db表,...)。
  2. 客户的请求只会将项目添加到该列表中。
  3. 您将根据需要培养尽可能多的工人,他们可以是一个,几个,也可以根据需要进行自动缩放。
  4. 每个工人都会(原子)检查他是否必须处理工作。注意:最佳方法是在列表中有一个挂钩,以便在列表中发生更改时会得到推动,以便不需要在列表中重复读取(工人只是等待最近的时刻)。

这种方法的值得注意的属性:

  1. 可能会同时运行作业。
  2. 节点可能会损坏,花费很长时间等...而不会影响未决的工作(您只能看到没有空闲工人来自动化)。
  3. 您可以轻松地检查工作是否丢失(例如,运行的节点损坏了),是否尝试过几次运行,没有成功等...
  4. 状态是持久的,您可以检查是否错过了工作,请恢复它们等等...
  5. 根据您需要解决方案的效率,它可以非常精心(挂钩,自动缩放状态等)或非常简单(简单的 Begin trans;从时间&gt; = NOW = 0订单按时间限制。

The best solution depends (as almost always) on the context in which your infrastructure will have to work.

You can use @Scheduled (i.e. Spring Scheduled Task running in clustered environment ) but it does not perform well in clusters (there is usually only one node running jobs).

I am going to suggest a solution with a good balance between simplicity, efficiency and reliability. I will discuss some of its properties later.

Suggested solution:

  1. uses an ordered list with guaranteed atomicity (message queue, redis sorted list, db table, ...).
  2. a request from a customer, it will simply add an item to that list.
  3. you will raise as many workers as you need, they can be one, several or with auto-scaling as needed.
  4. each worker will check (atomically) if he has to process a job. NOTE: the optimal way is to have a hook against the list, so that they get a push when there are changes in the list, so that recurring reads on the list are not necessary (the workers simply wait for the nearest moment).

Noteworthy properties of this approach:

  1. there may be one or more nodes running jobs simultaneously.
  2. a node can become corrupted, take a long time, etc... without affecting the pending jobs (you can do autoscaling just by seeing that there are no idle workers).
  3. you can easily check if a job was lost (e.g. the node running it got corrupted), if it has been tried to run several times without success, etc...
  4. the status is persistent and you can check if jobs were missed, resume them, etc...
  5. depending on how efficient you need your solution to be, it can be very elaborate (hooks, auto-scaling state, etc...) or very simple (a simple begin trans; select 1 id from jobs where time >= now and running = 0 order by time limit 1; ... update jobs set running = 1 where id = ?; ...; commit trans).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文