分布式后台作业调度器JobRunr介绍 - JAXenter


JobRunr 分析所有作业并将其序列化为 SQL 或 NoSQL 数据库的可读 JSON。如果创建了太多后台作业,您可以通过启动更多应用程序实例来水平扩展。由于作业以 JSON 格式存储在中央数据库中,因此工作负载可以分布在多个 JVM 上。
 
JobRunr 是一个库,您可以将其嵌入到现有应用程序中以启用后台作业的调度。作业可以是在后台线程中运行的短期或长期进程。一个典型的用例是将长时间运行的进程从 Web 请求卸载到后台线程,从而为最终用户带来更好的体验。
 
JobRunr 分析所有作业并将其序列化为 SQL 或 NoSQL 数据库的可读 JSON。如果创建了太多后台作业,您可以通过启动更多应用程序实例来水平扩展。由于作业以 JSON 格式存储在中央数据库中,因此工作负载可以分布在多个 JVM 上。一旦您的应用程序的新实例启动,JobRunr 就会自动开始处理作业。为了确保同一个作业不会被多次处理,它使用了乐观锁定。没有人喜欢清理,这就是 JobRunr 也是自我维护的原因 - 所有成功的作业将在可配置的时间后自动删除。
有时您不想立即运行作业——您需要它在明天运行(例如,用户注册后的第二天),或者您可能想要运行重复性作业。所有这些都是开箱即用的。
生活并不总是完美无缺的——如果后台作业失败(例如,由于依赖的 API 关闭),它会通过智能退避策略自动重试。
JobRunr 还带有一个内置仪表板,可让您监控所有作业。
 
您可以轻松创建后台作业:

  • 通过 Java 8 lambda,您可以重用任何现有服务
  • 或通过 JobRequest 和 JobRequestHandler

在本文中,您将学习如何通过 Java 8 lambda 和 JobRequest 调度一个简单的后台作业。
 
Maven依赖:
<dependency>
    <groupId>org.jobrunr</groupId>
    <artifactId>jobrunr-spring-boot-starter</artifactId>
    <version>4.0.8</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.6.1</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.1.210</version>
</dependency>

在这里,您要添加 3 个依赖项:

  • 启用 JobRunr 和 Spring Boot 之间的集成的`jobrunr-spring-boot-starter`。
  • 此`spring-boot-starter-data-jpa`并不是真正必要的,但它会有所帮助,因为它会自动为您创建一个 DataSource。
  • `h2`您将用于存储所有作业状态的数据库

 
JobRunr 默认只启用作业调度程序。由于后台作业服务器和仪表板仅可选择加入,因此您需要向 Spring 添加一些属性`application.properties`:
  1. org.jobrunr.background-job-server.enabled=true
  2. org.jobrunr.dashboard.enabled=true

第一个属性告诉 JobRunr 启用后台作业服务器,以便实际处理作业。第二个属性启用 JobRunr 仪表板。
 
作业存储:
默认情况下,JobRunr 将尝试使用您现有的`javax.sql.DataSource`或任何受支持的 NoSQL 客户端来存储所有与作业相关的信息。当您将依赖项添加到 时`spring-boot-starter-data-jpa`,已自动创建了一个 DataSource,因此您已准备就绪。
 
用法
  • 通过 Job Lambda

要将 JobRunr 与 Job Lambda 一起使用,您首先需要注入一些 Spring Bean:
@Inject
private JobScheduler jobScheduler;
 
@Inject
private SampleJobService sampleJobService;

`JobScheduler`是 JobRunr 提供的一个 bean,允许您将新作业排入队列或调度。
`SampleJobService` 可以是您想要调用可能需要一些时间来处理的方法的任何 Spring bean。它也可以是您想要添加一些额外弹性的方法,因为 JobRunr 会在发生异常时自动重试该方法。
现在,您可以轻松创建作业:

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob());

传递参数也是可以的:

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob("Hello! I will be executed in a Background process, perhaps even a different JVM"));

上述两个调用将确保 JobRunr 分析给定的 lambda,它将存储在数据库中,并且下一个可用的专用工作者worker将处理它。
 

  • 通过 JobRequest 和 JobRequestHandler

你也可以通过JobRequest来创建一个作业。这将涉及到创建一个 "JobRequest "和 "JobRequestHandler",并对实际工作进行排队。
public class SampleJobRequest implements JobRequest {
 
    private final String input;
 
    // needed for deserialization by Jackson
    protected TestJobRequest() {
        this(null);
    }
 
    public TestJobRequest(String input) {
        this(input);
    }
 
    @Override
    public Class<SampleJobRequestHandler> getJobRequestHandler() {
        return SampleJobRequestHandler.class;
    }
 
    public String getInput() {
        return input;
    }
}

在这里,你首先创建一个`SampleJobRequest`,它可以接受你在创建作业时可用的参数。这个`JobRequest'还需要实现一个叫做`getJobRequestHandler'的方法。这个方法必须返回包含实际业务逻辑/后台工作的类。

接下来,你需要创建一个`SampleJobRequestHandler`,它将包含你的实际背景工作者worker和业务逻辑。要做到这一点,必须实现一个`run'方法。当背景工作运行时,它将被提供给你上面创建的输入。

@Service
public static class SampleJobRequestHandler implements JobRequestHandler<SampleJobRequest> {
 
    @Override
    public void run(SampleJobRequest jobRequest) {
        System.out.println("Running sample job request in background: " + jobRequest.getInput());
    }
}

现在只剩下一件事了:排队作业。你可以按以下方式进行:
@Inject
private JobRequestScheduler jobRequestScheduler;
 
...
         
jobRequestScheduler.enqueue(new SampleJobRequest("Hello"));

结论
在完成这篇文章后,你已经使用Spring Boot和JobRunr创建了你的第一个后台作业。 这里的重要细节是,你可以用最少的代码创建一个后台作业,甚至可以在与你安排它的地方不同的JVM中运行。在这里,我们只是简单地触及了JobRunr的一个功能,然而,它提供了更多的功能,如预定作业、循环作业等等。

本文的完整源代码可以在Github上找到。