Перейти к основному содержимому

Введение в Spring Cloud Task

· 6 мин. чтения

1. Обзор

Цель Spring Cloud Task — предоставить функциональность создания недолговечных микросервисов для приложения Spring Boot .

В Spring Cloud Task у нас есть возможность динамического запуска любой задачи, выделения ресурсов по требованию и получения результатов после завершения задачи.

Задачи — это новый примитив в Spring Cloud Data Flow, позволяющий пользователям выполнять практически любое приложение Spring Boot в качестве краткосрочной задачи .

2. Разработка простого приложения задачи

2.1. Добавление соответствующих зависимостей

Для начала мы можем добавить раздел управления зависимостями с spring-cloud-task-dependencies:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-task-dependencies</artifactId>
<version>2.2.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Это управление зависимостями управляет версиями зависимостей через область импорта.

Нам нужно добавить следующие зависимости:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-task</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-task-core</artifactId>
</dependency>

Это ссылка на Maven Central из spring-cloud-task-core .

Теперь, чтобы запустить наше приложение Spring Boot, нам нужен spring-boot-starter с соответствующим родителем.

Мы собираемся использовать Spring Data JPA в качестве инструмента ORM, поэтому нам также нужно добавить зависимость для него:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.1</version>
</dependency>

Подробности начальной загрузки простого приложения Spring Boot с помощью Spring Data JPA доступны здесь .

Мы можем проверить новейшую версию spring-boot-starter-parent на Maven Central .

2.2. Аннотация @EnableTask _

Чтобы запустить функциональность Spring Cloud Task, нам нужно добавить аннотацию @EnableTask :

@SpringBootApplication
@EnableTask
public class TaskDemo {
// ...
}

В аннотации представлен класс SimpleTaskConfiguration , который, в свою очередь, регистрирует TaskRepository и его инфраструктуру . По умолчанию карта в памяти используется для хранения состояния TaskRepository .

Основная информация TaskRepository моделируется в классе TaskExecution . Отмеченные поля этого класса: taskName , startTime , endTime , exitMessage . В exitMessage хранится доступная информация во время выхода.

Если выход вызван сбоем в каком-либо событии приложения, здесь будет храниться полная трассировка стека исключений.

Spring Boot предоставляет интерфейс ExitCodeExceptionMapper , который сопоставляет неперехваченные исключения с кодами выхода, что позволяет проводить тщательную отладку . Облачная задача сохраняет информацию в источнике данных для будущего анализа.

2.3. Настройка источника данных для TaskRepository ``

Карта в памяти для хранения TaskRepository исчезнет после завершения задачи, и мы потеряем данные, связанные с событиями задачи. Для хранения в постоянном хранилище мы будем использовать MySQL в качестве источника данных с Spring Data JPA.

Источник данных настраивается в файле application.yml . Чтобы настроить Spring Cloud Task для использования предоставленного источника данных в качестве хранилища TaskRepository , нам нужно создать класс, расширяющий DefaultTaskConfigurer .

Теперь мы можем отправить настроенный источник данных в качестве аргумента конструктора конструктору суперкласса:

@Autowired
private DataSource dataSource;

public class HelloWorldTaskConfigurer extends DefaultTaskConfigurer{
public HelloWorldTaskConfigurer(DataSource dataSource){
super(dataSource);
}
}

Чтобы использовать приведенную выше конфигурацию в действии, нам нужно аннотировать экземпляр DataSource аннотацией @Autowired и внедрить экземпляр в качестве аргумента-конструктора bean-компонента HelloWorldTaskConfigurer , определенного выше:

@Bean
public HelloWorldTaskConfigurer getTaskConfigurer() {
return new HelloWorldTaskConfigurer(dataSource);
}

На этом настройка для хранения TaskRepository в базе данных MySQL завершена.

2.4. Реализация

В Spring Boot мы можем выполнить любую задачу непосредственно перед тем, как приложение завершит свой запуск. Мы можем использовать интерфейсы ApplicationRunner или CommandLineRunner для создания простой задачи.

Нам нужно реализовать метод run этих интерфейсов и объявить реализующий класс как bean-компонент:

@Component
public static class HelloWorldApplicationRunner
implements ApplicationRunner {

@Override
public void run(ApplicationArguments arg0) throws Exception {
System.out.println("Hello World from Spring Cloud Task!");
}
}

Теперь, если мы запустим наше приложение, мы должны получить нашу задачу, производящую необходимый вывод с необходимыми таблицами, созданными в нашей базе данных MySQL, регистрирующими данные о событиях Задачи.

3. Жизненный цикл Spring Cloud Task

Вначале мы создаем запись в TaskRepository . Это указывает на то, что все bean-компоненты готовы к использованию в приложении, а метод run интерфейса Runner готов к выполнению.

По завершении выполнения метода запуска или при любом сбое события ApplicationContext TaskRepository будет обновлен другой записью.

В течение жизненного цикла задачи мы можем регистрировать прослушиватели, доступные из интерфейса TaskExecutionListener . Нам нужен класс, реализующий интерфейс с тремя методами — onTaskEnd , onTaksFailed и onTaskStartup , срабатывающими в соответствующих событиях Задачи.

Нам нужно объявить bean-компонент реализующего класса в нашем классе TaskDemo :

@Bean
public TaskListener taskListener() {
return new TaskListener();
}

4. Интеграция с Spring Batch

Мы можем выполнить Spring Batch Job как Task и регистрировать события выполнения Job с помощью Spring Cloud Task. Чтобы включить эту функцию, нам нужно добавить пакетные зависимости, относящиеся к загрузке и облаку:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-task-batch</artifactId>
</dependency>

Вот ссылка на Maven Central из spring-cloud-task-batch .

Чтобы настроить задание как задачу, нам нужно зарегистрировать компонент Job в классе JobConfiguration :

@Bean
public Job job2() {
return jobBuilderFactory.get("job2")
.start(stepBuilderFactory.get("job2step1")
.tasklet(new Tasklet(){
@Override
public RepeatStatus execute(
StepContribution contribution,
ChunkContext chunkContext) throws Exception {
System.out.println("This job is from ForEach");
return RepeatStatus.FINISHED;
}
}).build()).build();
}

Нам нужно украсить класс TaskDemo аннотацией @EnableBatchProcessing :

//..Other Annotation..
@EnableBatchProcessing
public class TaskDemo {
// ...
}

Аннотация @EnableBatchProcessing включает функции Spring Batch с базовой конфигурацией, необходимой для настройки пакетных заданий.

Теперь, если мы запустим приложение, аннотация @EnableBatchProcessing инициирует выполнение Spring Batch Job, а Spring Cloud Task будет регистрировать события выполнения всех пакетных заданий с другим Task, выполняемым в базе данных springcloud .

5. Запуск задачи из потока

Мы можем запускать задачи из Spring Cloud Stream. Для этой цели у нас есть аннотация @EnableTaskLaucnher . Как только мы добавим аннотацию в приложение Spring Boot, будет доступен TaskSink:

@SpringBootApplication
@EnableTaskLauncher
public class StreamTaskSinkApplication {
public static void main(String[] args) {
SpringApplication.run(TaskSinkApplication.class, args);
}
}

TaskSink получает сообщение из потока, который содержит GenericMessage , содержащий TaskLaunchRequest в качестве полезной нагрузки. Затем он запускает задачу на основе координат, указанных в запросе на запуск задачи.

Чтобы TaskSink работал, нам нужен bean-компонент, реализующий интерфейс TaskLauncher . В целях тестирования мы издеваемся над реализацией здесь:

@Bean
public TaskLauncher taskLauncher() {
return mock(TaskLauncher.class);
}

Здесь нужно отметить, что интерфейс TaskLauncher доступен только после добавления зависимости spring-cloud-deployer-local :

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-deployer-local</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>

Мы можем проверить, запущена ли задача, вызвав ввод интерфейса Sink :

public class StreamTaskSinkApplicationTests {

@Autowired
private Sink sink;

//
}

Теперь мы создаем экземпляр TaskLaunchRequest и отправляем его как полезную нагрузку объекта GenericMessage< TaskLaunchRequest > . Затем мы можем вызвать входной канал приемника , сохраняя объект GenericMessage в канале. ``

6. Заключение

В этом руководстве мы рассмотрели, как работает Spring Cloud Task и как настроить его для регистрации событий в базе данных. Мы также наблюдали, как задание Spring Batch определяется и хранится в TaskRepository . Наконец, мы объяснили, как мы можем запускать Task из Spring Cloud Stream.

Как всегда, код доступен на GitHub .