Scheduling Periodic Tasks

现代应用程序通常需要定期运行特定任务。在本指南中,您将学习如何计划定期任务。

Modern applications often need to run specific tasks periodically. In this guide, you learn how to schedule periodic tasks.

如果您需要集群调度器,请使用 Quartz extension

If you need a clustered scheduler use the Quartz extension.

Prerequisites

Unresolved directive in scheduler.adoc - include::{includes}/prerequisites.adoc[]

Architecture

在本指南中,我们创建了一个可使用 HTTP 访问的简单应用程序以获取计数器的当前值。此计数器会定期(每 10 秒)递增。

In this guide, we create a straightforward application accessible using HTTP to get the current value of a counter. This counter is periodically (every 10 seconds) incremented.

scheduling task architecture

Solution

我们建议您遵循接下来的部分中的说明,按部就班地创建应用程序。然而,您可以直接跳到完成的示例。

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

克隆 Git 存储库: git clone {quickstarts-clone-url},或下载 {quickstarts-archive-url}[存档]。

Clone the Git repository: git clone {quickstarts-clone-url}, or download an {quickstarts-archive-url}[archive].

该解决方案位于 scheduler-quickstart directory中。

The solution is located in the scheduler-quickstart directory.

Creating the Maven project

首先,我们需要一个新项目。使用以下命令创建一个新项目:

First, we need a new project. Create a new project with the following command:

Unresolved directive in scheduler.adoc - include::{includes}/devtools/create-app.adoc[]

它生成一个新项目,包括:

It generates a new project including:

  • a landing page accessible on http://localhost:8080

  • example Dockerfile files for both native and jvm modes

  • the application configuration file

此项目还会导入 Quarkus REST(以前的 RESTEasy Reactive)和调度程序扩展。

The project also imports the Quarkus REST (formerly RESTEasy Reactive) and scheduler extensions.

如果您已配置 Quarkus 项目,则可以通过在项目基本目录中运行以下命令将 `scheduler`扩展添加到项目中:

If you already have your Quarkus project configured, you can add the scheduler extension to your project by running the following command in your project base directory:

Unresolved directive in scheduler.adoc - include::{includes}/devtools/extension-add.adoc[]

这会将以下内容添加到构建文件中:

This will add the following to your build file:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-scheduler</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-scheduler")

Creating a scheduled job

在 `org.acme.scheduler`包中,创建 `CounterBean`类,内容如下:

In the org.acme.scheduler package, create the CounterBean class, with the following content:

package org.acme.scheduler;

import java.util.concurrent.atomic.AtomicInteger;
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.scheduler.Scheduled;
import io.quarkus.scheduler.ScheduledExecution;

@ApplicationScoped              (1)
public class CounterBean {

    private AtomicInteger counter = new AtomicInteger();

    public int get() {  (2)
        return counter.get();
    }

    @Scheduled(every="10s")     (3)
    void increment() {
        counter.incrementAndGet(); (4)
    }

    @Scheduled(cron="0 15 10 * * ?") 5
    void cronJob(ScheduledExecution execution) {
        counter.incrementAndGet();
        System.out.println(execution.getScheduledFireTime());
    }

    @Scheduled(cron = "{cron.expr}") 6
    void cronJobWithExpressionInConfig() {
       counter.incrementAndGet();
       System.out.println("Cron expression configured in application.properties");
    }
}
1 Declare the bean in the application scope
2 The get() method allows retrieving the current value.
3 Use the @Scheduled annotation to instruct Quarkus to run this method every 10 seconds provided a worker thread is available (Quarkus is using 10 worker threads for the scheduler). If it is not available the method invocation should be re-scheduled by default i.e. it should be invoked as soon as possible. The invocation of the scheduled method does not depend on the status or result of the previous invocation.
4 The code is pretty straightforward. Every 10 seconds, the counter is incremented.
5 Define a job with a cron-like expression. The annotated method is executed at 10:15am every day.
6 Define a job with a cron-like expression cron.expr which is configurable in application.properties.

Updating the application configuration file

编辑 application.properties 文件并添加 cron.expr 配置:

Edit the application.properties file and add the cron.expr configuration:

# By default, the syntax used for cron expressions is based on Quartz - https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html
# You can change the syntax using the following property:
# quarkus.scheduler.cron-type=unix
cron.expr=*/5 * * * * ?

Creating the REST resource

创建如下 CountResource 类:

Create the CountResource class as follows:

package org.acme.scheduler;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/count")
public class CountResource {

    @Inject
    CounterBean counter;            (1)


    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "count: " + counter.get();  (2)
    }
}
1 Inject the CounterBean
2 Send back the current counter value

Package and run the application

使用以下内容运行应用程序:

Run the application with:

Unresolved directive in scheduler.adoc - include::{includes}/devtools/dev.adoc[]

在另一个终端中,运行 curl localhost:8080/count 以检查计数器值。几秒钟后,重新运行 curl localhost:8080/count 以验证计数器已被增量。

In another terminal, run curl localhost:8080/count to check the counter value. After a few seconds, re-run curl localhost:8080/count to verify the counter has been incremented.

观察控制台以验证消息 Cron expression configured in application.properties 已显示,表明使用在 application.properties 配置的表达式配置的 Cron 作业已触发。

Observe the console to verify that the message Cron expression configured in application.properties has been displayed indicating that the cron job using an expression configured in application.properties has been triggered.

和往常一样,可以使用以下命令打包应用程序:

As usual, the application can be packaged using:

Unresolved directive in scheduler.adoc - include::{includes}/devtools/build.adoc[]

并且使用 java -jar target/quarkus-app/quarkus-run.jar 执行。

And executed with java -jar target/quarkus-app/quarkus-run.jar.

你还可以按如下方式生成本机可执行文件:

You can also generate the native executable with:

Unresolved directive in scheduler.adoc - include::{includes}/devtools/build-native.adoc[]

Scheduler Configuration Reference

Unresolved directive in scheduler.adoc - include::{generated-dir}/config/quarkus-scheduler.adoc[]