Статьи

Перезапуск Spring Batch

Прежде всего, я хотел бы поблагодарить замечательных людей из Spring, которые посвятили бесчисленное количество часов своего времени обеспечению жизнеспособности заданий Spring Batch и, казалось бы, волшебной способности выпустить перезапуск на работе! Спасибо за этот элегантный набор инструментов, который позволяет нам пробираться сквозь массивные наборы данных, в то же время позволяя нам отряхиваться, когда мы падаем!

Признавая, что мне еще предстоит многому научиться, я хотел бы поделиться своими хорошо усвоенными уроками в мире перезапускаемости. В этом посте будет рассказано, как определить неправильное использование Step & Job ExecutionContext в Spring Batch, а также как написать полезные полезные компоненты для Spring Batch.

Statefulness!

Statefulness — это в основном модный разговор для bean-компонентов, которые имеют глобальные переменные, которые меняются.

В качестве примера возьмем однодолларовую купюру. Это будет считаться безгражданством, так как его значение является постоянным. С другой стороны, возьмите акцию как Google; его цена колеблется, и его стоимость будет считаться переменной (или с состоянием).

ExecutionContext

Чтобы сохранить состояние, Spring предоставляет нам доступ к ExecutionContext для Step и Job, чтобы мы могли обрабатывать информацию, необходимую для правильного выполнения и выполнения нашей работы.

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

Какую информацию можно сохранить в ExecutionContext?

Технически, я думаю, любой сериализуемый объект может быть помещен в ExecutionContext в любое время, но я бы сказал, что это опасный способ мышления. Обновления ExecutionContext должны обрабатываться очень транзакционным способом.

Какая информация должна быть сохранена в ExecutionContext?

Я бы порекомендовал хранить здесь только простые / псевдопримитивные простые значения. Если вы хотите спокойно спать по ночам, я бы также рекомендовал записывать эти значения только через ItemProcessor ИЛИ метод, аннотированный @BeforeStep или @AfterStep.

Что не должно случиться?

ExecutionContext не должен вводиться и передаваться в основной бизнес-логике. Значения контекста не должны обновляться в середине выполнения шага. Кроме того, следует избегать введения изменяемого объекта-держателя значения в ExecutionContext, так как его ссылка может легко повредить значения за пределами транзакции.

Когда я вижу подобные примеры в коде, я считаю их угрозой перезапуску приложения и отказываюсь сертифицировать перезапуск этого приложения.

В общем, не существует универсального подхода к обеспечению того, чтобы код вашей работы был написан так, чтобы гарантировать правильную обработку информации о состоянии. Однако я скажу вам, что вам нужно подумать о:

  • Как завершаются транзакции (распределенные, разделенные, многопоточные и т. Д.)
  • Как отслеживается прогресс чанка?
  • Как ваши чтения отсортированы / сгруппированы?
  • Какая информация понадобится при перезапуске?

Вот пример общей практики для обновления информации о состоянии работы:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.springframework.batch.item.*;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/*This could be a reader, or a writer, or maybe a processor...
  you need to identify when and where it is appropriate to
  perform these tracking activities. Remember to think about restarts! */
@Component
@StepScope
public class FooComponent implements ItemStream{
 
// a perfectly acceptable way to read a value from an ExecutionContext from anywhere!
@Value(“#stepExecutionContext[‘fooStatefulCount’]”)
long statefulCount = 0; // a read count perhaps?
 
public static final String KEY = "bar";
public void open(ExecutionContext cxt) throws ItemStreamException {
    cxt.put(KEY, statefulCount);
}
public void update(ExecutionContext cxt) throws ItemStreamException {
    cxt.put(KEY, statefulCount);
}  
public void close() throws ItemStreamException {}
}

Если вы хотите более подробный пример, посмотрите метод open в AbstractItemCountingItemStreamItemReader !

Последние мысли

Мой последний совет — чтобы другие разработчики стремились быть принципиально и совершенно обычными при написании вашего кода. Простота обеспечит понимание будущего, и впоследствии владельцы бизнеса будут дорожить вашим подарком приложения, которое в значительной степени не имеет технических долгов.

Ссылка: Spring Batch Restartability от нашего партнера JCG Райана Маккалоу в блоге Keyhole Software .