In the last article, we showed you how to implement Scheduled tasks using the @Scheduled annotation that comes with Spring Boot. The limitation of this method is also mentioned at the end of the article. In a cluster environment, if the execution or operation of a task depends on some shared resources, there will be contention. If you do not introduce mechanisms such as distributed locking for scheduling, unexpected execution results may occur. As a result, the @Scheduled annotations are more likely to be used for Scheduled tasks related to the maintenance of the single instance itself, such as periodically cleaning files in a directory of the service instance, periodically uploading statistics for this instance, and so on.

So, when it comes to actually implementing the business logic, isn’t there a better scheduled task scenario? Today we will introduce an old distributed timed task framework, use case under Spring Boot.

Elasitc Job

Elastic Job is a distributed task scheduling framework created by Dangdang, and has been added to the Apache Foundation.

There are two branches under this item: ElasticJob-Lite and ElasticJob-Cloud. Elasticjob-lite is a lightweight task management solution, which is used in the following examples in this article. Elasticjob-cloud is heavier because it uses a container to manage tasks and isolate resources.

For more information about ElasticJob, you can also click here to learn more about ElasticJob.

Began to try

Say so much, try together!

Step 1: Create a basic Spring Boot project, if not already? So check out this quick guide.

Step 2: Add an ElasticJob-Lite starter in pom.xml

<dependencies>
    <dependency>
        <groupId>org.apache.shardingsphere.elasticjob</groupId>
        <artifactId>elasticjob-lite-spring-boot-starter</artifactId>
        <version>3.0.0</version>
    </dependency>

    // ...
</dependencies>
Copy the code

Step 3: Create a simple task

@Slf4j
@Service
public class MySimpleJob implements SimpleJob {

    @Override
    public void execute(ShardingContext context) {
        log.info("MySimpleJob start : didispace.com {}", System.currentTimeMillis()); }}Copy the code

Step 4: Edit the configuration file

elasticjob.reg-center.server-lists=localhost:2181
elasticjob.reg-center.namespace=didispace

elasticjob.jobs.my-simple-job.elastic-job-class=com.didispace.chapter72.MySimpleJob
elasticjob.jobs.my-simple-job.cron=0/5 * * * *?
elasticjob.jobs.my-simple-job.sharding-total-count=1
Copy the code

There are two main parts:

Part 1: ElasticJob. reg-center: Specifies the registry and namespace of elasticJob

Part 2: Task configuration. Start with ElasticJob. jobs. My-simple-job is the name of the task. Configuration-elastic-job-class is the implementation class of the task, cron is the execution rule expression, and sharding-total-count is the total number of task fragments. We can use this parameter to divide tasks and realize parallel processing. I’m going to set it to 1, and we’ll talk about sharding later.

Run and test

With all that done, we can try running the above application because we need To use ZooKeeper to coordinate the scheduling of tasks in a distributed environment. So, you need to install ZooKeeper locally and then start it. Note: The configuration of ElasticJob. reg-center.server-lists can be changed according to the ZooKeeper address and port you are using.

After starting the Spring Boot application above, we can see the following log output:

The 2021-07-20 15:33:39. 56365-541 the INFO [main] org. Quartz. Impl. StdSchedulerFactory: Quartz Scheduler 'my-simple job' initialized from an Enumerated properties instance. 2021-07-20 15:33:39.541 INFO 56365 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler version: The 2021-07-20 15:33:39 2.3.2. 56365-551 the INFO [main] org.apache.curator.utils.Com patibility: Using org. Apache. Zookeeper. Server. Quorum. MultipleAddresses 15:33:40 2021-07-20. 56365-067 the INFO [main] c.d.chapter72.Chapter72Application : Started Chapter72Application in 3.25 seconds (JVM running for 4.965) 2021-07-20 15:33:40.069 INFO 56365 -- [main] .s.b.j.ScheduleJobBootstrapStartupRunner : Starting ElasticJob Bootstrap. 2021-07-20 15:33:40. 078 INFO 56365 - [the main] org. Quartz. Core. QuartzScheduler: Scheduler my-simple-job_$_NON_CLUSTERED started. 2021-07-20 15:33:40.078 INFO 56365 -- [main] clustered started. .s.b.j.ScheduleJobBootstrapStartupRunner : ElasticJob Bootstrap started. 2021-07-20 15:33:45.157 INFO 56365 -- [le-job_worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : Didispace.com 1626766425157 15:33:50 2021-07-20. 56365-010 the INFO] [le - job_Worker - 1 com. Didispace. Chapter72. MySimpleJob  : MySimpleJob start : Didispace.com 1626766430010 15:33:55 2021-07-20. 56365-013 the INFO] [le - job_Worker - 1 com. Didispace. Chapter72. MySimpleJob  : MySimpleJob start : didispace.com 1626766435013Copy the code

Since the task is distributed, we start another one (note that when the same machine is started, there will be port conflicts, you can add -dserver.port =8081 to the start command to distinguish ports), and the second start service log prints similar content

The 2021-07-20 15:34:06. 56371-430 the INFO [main] org. Quartz. Impl. StdSchedulerFactory: Quartz Scheduler 'my-simple job' initialized from an Enumerated properties instance. 2021-07-20 15:34:06.430 INFO 56371 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler version: The 2021-07-20 15:34:06 2.3.2. 56371-436 the INFO [main] org.apache.curator.utils.Com patibility: Using org. Apache. Zookeeper. Server. Quorum. MultipleAddresses 15:34:06 2021-07-20. 56371-786 the INFO [main] c.d.chapter72.Chapter72Application : Started Chapter72Application in 1.446 seconds (JVM running for 1.884) 2021-07-20 15:34:06.787 INFO 56371 -- [main] .s.b.j.ScheduleJobBootstrapStartupRunner : Starting ElasticJob Bootstrap. 2021-07-20 15:34:06. 792 INFO 56371 - [the main] org. Quartz. Core. QuartzScheduler: Scheduler my-simple-job_$_NON_CLUSTERED started. 2021-07-20 15:34:06.792 INFO 56371 -- [main] .s.b.j.ScheduleJobBootstrapStartupRunner : 2021-07-20 15:34:10.182 INFO 56371 -- [le-job_worker-1] ElasticJob Bootstrap started. com.didispace.chapter72.MySimpleJob : MySimpleJob start : Didispace.com 1626766450182 15:34:15 2021-07-20. 56371-010 the INFO] [le - job_Worker - 1 com. Didispace. Chapter72. MySimpleJob  : MySimpleJob start : Didispace.com 1626766455010 15:34:20 2021-07-20. 56371-013 the INFO] [le - job_Worker - 1 com. Didispace. Chapter72. MySimpleJob  : MySimpleJob start : didispace.com 1626766460013Copy the code

At this point, after looking back at the first application started earlier, the log output stops. Since we set the total number of shards to 1, once this task starts, only one instance will take over. This avoids the problem of executing the same logic multiple times at the same time. This also enables high availability of task execution. For example, you can try to terminate the second application that started (and is printing logs). You can see that the first application started (which had stopped producing logs) continues to print the task logs.

In the whole implementation process, we did not manually write any distributed lock code to implement the task scheduling logic, only need to pay attention to the task logic itself, and then control the segmentation of the task through the configuration of sharding, can easily realize the scheduled task management in the distributed cluster environment. Is this easier to implement than @Scheduled in complex scenarios?

Remember to write their own hands to write, so deeper experience oh! If you run into problems, pull the code sample at the end of the article and see if anything is configured differently. In the next installment, we’ll continue with some advanced content about timed tasks. If you are interested in this content, you can bookmark this series of tutorials, Spring Boot 2.x Basics tutorial, click there! . If you encounter difficulties in the learning process, you can join our Spring technology exchange group to participate in the communication and discussion, so as to better learn and progress!

Code sample

The complete project for this article can be viewed in the following chapter7-2 directory in the repository:

  • Github:github.com/dyc87112/Sp…
  • Gitee:gitee.com/didispace/S…

If you like this article, welcomeStarSupport, your concern is the power of my persistence!

Welcome to pay attention to my public number: program ape DD, to share the outside can not see the dry goods and thinking!