Skip to content

Commit

Permalink
new features: add distributed scheduling support. (#3732)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaohuitc authored May 31, 2024
1 parent bc0e5a3 commit 79bca1e
Show file tree
Hide file tree
Showing 27 changed files with 4,100 additions and 5 deletions.
27 changes: 27 additions & 0 deletions spring-cloud-alibaba-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<spring.ai.version>0.8.1</spring.ai.version>
<dashscope-sdk-java.version>2.14.0</dashscope-sdk-java.version>

<!-- scheduling -->
<shedlock.version>4.23.0</shedlock.version>
<schedulerx.worker.version>1.11.4</schedulerx.worker.version>

<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
Expand Down Expand Up @@ -185,6 +189,23 @@
<version>${rocketmq.version}</version>
</dependency>

<!-- Alibaba scheduling -->
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>${shedlock.version}</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>${shedlock.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun.schedulerx</groupId>
<artifactId>schedulerx2-worker</artifactId>
<version>${schedulerx.worker.version}</version>
</dependency>

<!-- Own dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
Expand Down Expand Up @@ -258,6 +279,12 @@
<version>${revision}</version>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>
<version>${revision}</version>
</dependency>

<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
Expand Down
8 changes: 4 additions & 4 deletions spring-cloud-alibaba-examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
<module>rocketmq-example/rocketmq-example-common</module>
<module>rocketmq-example/rocketmq-tx-example</module>
<module>rocketmq-example/rocketmq-pollable-consume-example</module>

<module>spring-cloud-bus-rocketmq-example</module>
<module>spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example</module>
<module>spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-consul-example</module>
Expand All @@ -52,9 +51,10 @@
<module>integrated-example/integrated-praise-consumer</module>
<module>integrated-example/integrated-common</module>
<module>integrated-example/integrated-frontend</module>
<module>ai-example/spring-cloud-ai-example</module>
<module>ai-example/spring-cloud-ai-rag-example</module>
</modules>
<module>ai-example/spring-cloud-ai-example</module>
<module>ai-example/spring-cloud-ai-rag-example</module>
<module>spring-cloud-scheduling-example</module>
</modules>


<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Spring Cloud Alibaba Scheduling Example

## Project description

Spring Cloud Alibaba Scheduling provides a timing task scheduling capability based on Spring Scheduling, supporting distributed scenarios for timing task scheduling. It offers a quick integration solution for timing task scheduling services in distributed scenarios.

The current offering is based on the open-source ShedLock for distributed lock acquisition, along with Alibaba Cloud's SchedulerX service [quick start](https://sca.aliyun.com/en/docs/2023/user-guide/schedulerx/quick-start/), Subsequent releases will provide access to more open-source solutions implementations.

## Project dependencies

### Access `spring-cloud-starter-alibaba-schedulerx`

Add the following dependencies to the project `pom.xml`

```xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>
</dependency>
```

## Project config description

In the Example project, two types of integration configuration modes are provided for `shedlock` and `schedulerx`, Select the required access mode configuration file in `application.yaml`, the example defaults to the shedlock solution.

### Solution 1. Distributed shedlock integration configuration

Edit the following configuration to the `application-schedulerx.yml`:
```yaml
spring:
cloud:
scheduling:
# Distributed mode: shedlock, schedulerx
# Set config value: shedlock
distributed-mode: shedlock
datasource:
driver-class: com.mysql.cj.jdbc.Driver
url: {jdbc_url}
username: {jdbc.username}
password: {jdbc.password}
```
You should replace `{jdbc_url}`,`{jdbc.username}`, and `{jdbc.password}` with your actual database connection information.

>️ Precautions:If there's no database instance can be used, please create a database instance first.

### Solution 2. Alibaba Cloud's SchedulerX integration configuration
Edit the following configuration to the `application-schedulerx.yml`:
```yaml
spring:
cloud:
scheduling:
# Distributed mode: shedlock, schedulerx
# Set config value: schedulerx
distributed-mode: schedulerx
schedulerx:
# This configuration is required, Please get it from aliyun schedulerx console
endpoint: acm.aliyun.com
namespace: aad167f6-xxxx-xxxx-xxxx-xxxxxxxxx
groupId: xxxxx
appKey: PZm1XXXXXXXXXXXX
# Optional config, if you need to sync task to schedulerx
# task-sync: true
# region-id: public
# aliyun-access-key: XXXXXXXXXXXX
# aliyun-secret-key: XXXXXXXXXXXX
# task-model-default: standalone
```
On Alibaba Cloud service, each account has be granted a free quota for schedulerx. For detailed instructions on how to configure and use cloud product integrations, please refer to the respective product documentation. Refer to: [SchedulerX Spring Task](https://www.alibabacloud.com/help/en/schedulerx/user-guide/spring-jobs)

## Start application

After completing the above selection and configuration, simply run the `ScheduleApplication` class in Example to start the application. The `SimpleJob` class in this example project includes two Spring scheduled tasks that run every minute. Upon starting, you can expect to see the following logs:

```text
2024-05-17T11:20:59.981+08:00 INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-17 11:20:59 do job1...
2024-05-17T11:20:59.985+08:00 INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-17 11:20:59 do job2...
```
### Distributed running verification

Create two application launch configurations in IDEA, each with the startup parameter `--server.port={port}` to start the corresponding application processes. The example project defaults to using `shedlock`,
We can observe that `job1` will be triggered by both applications, whereas `job2` which has been annotated with `@SchedulerLock` will only be triggered in one application at the same time.
![idea-server-port](images/idea-server-port.png)

- ScheduleApplication-1, startup parameter: `--server.port=18080`, application logs:
```text
2024-05-20T14:02:00.003+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:02:00 do job1...
2024-05-20T14:03:00.008+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:03:00 do job1...
2024-05-20T14:03:00.008+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:03:00 do job2...
2024-05-20T14:04:00.006+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:04:00 do job1...
2024-05-20T14:04:00.010+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:04:00 do job2...
2024-05-20T14:05:00.003+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:05:00 do job1...
```
- ScheduleApplication-2, startup parameter: `--server.port=18081`, application logs:
```text
2024-05-20T14:02:00.003+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:02:00 do job1...
2024-05-20T14:02:00.008+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:02:00 do job2...
2024-05-20T14:03:00.004+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:03:00 do job1...
2024-05-20T14:04:00.006+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:04:00 do job1...
2024-05-20T14:05:00.004+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:05:00 do job1...
2024-05-20T14:05:00.007+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:05:00 do job2...
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Spring Cloud Alibaba Scheduling Example

## 项目说明

Spring Cloud Alibaba Scheduling 提供了基于 Spring Scheduling 的定时任务调度能力,支持分布式场景下的定时任务调度,为分布式场景下的定时任务调度服务提供快速接入方案。

目前提供基于开源shedlock分布式抢锁模式,以及阿里云上SchedulerX服务的 [快速接入](https://sca.aliyun.com/docs/2023/user-guide/schedulerx/quick-start/) ,后续将提供更多实现的开源方案接入。

## 应用依赖

### 接入 `spring-cloud-starter-alibaba-schedulerx`

在项目 pom.xml 中加入以下依赖:

```xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>
</dependency>
```

## 配置说明

在Example工程中提供shedlock和schedulerx的两种接入配置模式(***二选一***),在`application.yaml`中选择需要的接入模式配置文件,案例中默认采用开源的shedlock方案。

### 方案一、分布式shedlock接入配置说明

在 application-schedulerx.yml 配置文件中修改以下配置:
```yaml
spring:
cloud:
scheduling:
# Distributed mode: shedlock, schedulerx
# Set config value: shedlock
distributed-mode: shedlock
datasource:
driver-class: com.mysql.cj.jdbc.Driver
url: {jdbc_url}
username: {jdbc.username}
password: {jdbc.password}
```
使用时请需要替换`{jdbc_url}`、`{jdbc.username}`、`{jdbc.password}`为实际自有的数据库连接信息。

>️ 注意:如未创建数据库,请先手动创建数据实例。

### 方案二、云产品SchedulerX接入配置说明
在 application-schedulerx.yml 配置文件中修改以下配置:
```yaml
spring:
cloud:
scheduling:
# Distributed mode: shedlock, schedulerx
# Set config value: schedulerx
distributed-mode: schedulerx
schedulerx:
# This configuration is required, Please get it from aliyun schedulerx console
endpoint: acm.aliyun.com
namespace: aad167f6-xxxx-xxxx-xxxx-xxxxxxxxx
groupId: xxxxx
appKey: PZm1XXXXXXXXXXXX
# Optional config, if you need to sync task to schedulerx
# task-sync: true
# region-id: public
# aliyun-access-key: XXXXXXXXXXXX
# aliyun-secret-key: XXXXXXXXXXXX
# task-model-default: standalone
```
阿里云上产品每个用户开通后都会有免费额度,详细云上产品接入配置使用说明,请参考:[阿里云SchedulerX Spring定时任务](https://help.aliyun.com/zh/schedulerx/user-guide/spring-jobs)

## 启动应用

在完成上述接入选择和配置后,直接运行Example中的 `ScheduleApplication`类即可启动运行。本案例工程中的`SimpleJob`类包含了两个每分钟执行一次的Spring定时任务,启动后可得到如下日志:
```text
2024-05-17T11:20:59.981+08:00 INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-17 11:20:59 do job1...
2024-05-17T11:20:59.985+08:00 INFO 66613 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-17 11:20:59 do job2...
```
### 分布式运行验证

在IDEA环境中创建两个应用启动项,各自分别配置启动参数`--server.port={应用端口}`,启动相应的应用进程。案例工程默认采用`shedlock`,
我们可以直接看到`job1`两个应用都会同时触发,而`job2`添加了`@SchedulerLock`注解则会同一时间点只会在一个应用进程中执行。
![idea-server-port](images/idea-server-port.png)

- ScheduleApplication-1,启动参数:`--server.port=18080`,定时任务运行日志如下:
```text
2024-05-20T14:02:00.003+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:02:00 do job1...
2024-05-20T14:03:00.008+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:03:00 do job1...
2024-05-20T14:03:00.008+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-1] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:03:00 do job2...
2024-05-20T14:04:00.006+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:04:00 do job1...
2024-05-20T14:04:00.010+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:04:00 do job2...
2024-05-20T14:05:00.003+08:00 INFO 80520 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:05:00 do job1...
```
- ScheduleApplication-2,启动参数:`--server.port=18081`,定时任务运行日志如下:
```text
2024-05-20T14:02:00.003+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:02:00 do job1...
2024-05-20T14:02:00.008+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:02:00 do job2...
2024-05-20T14:03:00.004+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-5] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:03:00 do job1...
2024-05-20T14:04:00.006+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-3] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:04:00 do job1...
2024-05-20T14:05:00.004+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-2] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:05:00 do job1...
2024-05-20T14:05:00.007+08:00 INFO 80596 --- [spring-cloud-alibaba-schedule-example] [ sca-schedule-4] c.a.c.examples.schedule.job.SimpleJob : time=2024-05-20 14:05:00 do job2...
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>com.alibaba.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-cloud-scheduling-example</artifactId>
<name>Spring Cloud Starter Alibaba Scheduling Example</name>
<description>Example demonstrating how to use Spring Cloud Schedule</description>
<packaging>jar</packaging>

<dependencies>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- database for shedlock start, JDBC data source configuration should be added -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- database for shedlock end -->

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2024-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.cloud.examples.schedule;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
* ScheduleApplication.
*
* @author yaohui
*/
@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {

public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
}

}
Loading

0 comments on commit 79bca1e

Please sign in to comment.