Введение в Spring Cloud

Вступление к весеннему облачному заданию

1. обзор

The goal of Spring Cloud Task is to provide the functionality of creating short-lived microservices for Spring Boot application.

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

Tasks is a new primitive within Spring Cloud Data Flow allowing users to execute virtually any Spring Boot application as a short-lived task.

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

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

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


    
        
            org.springframework.cloud
            spring-cloud-task-dependencies
            1.2.2.RELEASE
            pom
            import
        
    

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

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


    org.springframework.cloud
    spring-cloud-starter-task


    org.springframework.cloud
    spring-cloud-task-core

This - это ссылка на Maven Centralspring-cloud-task-core.

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

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


    org.springframework.boot
    spring-boot-starter-data-jpa
    1.5.10

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

Мы можем проверить последнюю версиюspring-boot-starter-parent onMaven Central.

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

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

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

The annotation brings SimpleTaskConfiguration class in the picture which in turns registers the TaskRepository and its infrastructure. По умолчанию карта в памяти используется для хранения статусаTaskRepository.

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

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

Spring Boot provides an interface ExitCodeExceptionMapper which maps uncaught exceptions to exit codes allowing scrutinized debug. Облачная задача хранит информацию в источнике данных для последующего анализа.

2.3. НастройкаDataSource дляTaskRepository

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

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

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

@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,we can execute any Task just before application finishes its startup.. Мы можем использовать интерфейсы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

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

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

During the task life-cycle, we can register listeners available from TaskExecutionListener interface. Нам нужен класс, реализующий интерфейс, имеющий три метода -onTaskEnd,onTaksFailed иonTaskStartup, запускаемых в соответствующих событиях Задачи.

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

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

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

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


    org.springframework.boot
    spring-boot-starter-batch


    org.springframework.cloud
    spring-cloud-task-batch

Here - это ссылка на Maven Centralspring-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 example");
                return RepeatStatus.FINISHED;
          }
    }).build()).build();
}

We need to decorate the TaskDemo class with @EnableBatchProcessing annotation:

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

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

Теперь, если мы запустим приложение, аннотация@EnableBatchProcessing вызовет выполнение Spring Batch Job, а Spring Cloud 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 в качестве полезной нагрузки. Затем он запускает задание на основе координат, указанных в запросе на запуск задания.

To have TaskSink functional, we require a bean configured that implements TaskLauncher interface. В целях тестирования мы имитируем реализацию здесь:

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

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


    org.springframework.cloud
    spring-cloud-deployer-local
    1.3.1.RELEASE

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

public class StreamTaskSinkApplicationTests {

    @Autowired
    private Sink sink;

    //
}

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

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

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

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