Правильный способ закрытия приложения Spring Boot после завершения определенной единицы работыJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Правильный способ закрытия приложения Spring Boot после завершения определенной единицы работы

Сообщение Anonymous »

У меня есть несколько постоянно работающих служб Spring Boot, выполняющих несколько различных задач. Например, у меня есть одна служба, которая читает из очереди служебной шины Azure с помощью Spring Cloud Stream, а затем отправляет сообщение методу в классе @Service. Я пытаюсь убедиться, что текущее обрабатываемое сообщение завершено, прежде чем разрешить завершение работы приложения при получении SIGTERM от Kubernetes. Мы пытаемся сделать это, чтобы наши данные не оказались в несогласованном состоянии.
В этом примере мы читаем из очереди в нашем классе приложения:

Код: Выделить всё

@Bean
public Consumer readMessage() {
return json -> {
try {
long[] eventIds = new Gson().fromJson(json, long[].class);
service.processMessage(eventIds);
}
catch (Exception ex) {
throw new RuntimeException("Exception in processing message..." + ex.getMessage());
}
};
}
Мы обрабатываем сообщение здесь:

Код: Выделить всё

@Service
public class MessageService {

//Autowired dependencies, etc.

public void processMessage(long[] eventIds) throws Exception {
// Perform work
.
.
.
// Now we can shut down safely
}
}
Я уже добавил следующие настройки Spring:

Код: Выделить всё

spring.lifecycle.timeout-per-shutdown-phase=15s
server.shutdown=graceful
Я также добавил перехватчик PreStop, который просто переводит в режим ожидания жизненный цикл контейнера в моем файле Deployment.yaml, но все, что он делает, это задерживает отправку SIGTERM в модуль, который закрывается. :

Код: Выделить всё

lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 15"]
Похоже, что это само по себе не помогает и вместо этого просто немедленно отключает службу независимо от того, какая обработка происходит. Я думаю, что добавление прослушивателя событий в ContextClosedEvent - это путь, но я все еще пытаюсь найти способ, кроме помещения Thread.sleep на какое-то произвольное время, которое должно быть достаточно длинным в EventListener

Код: Выделить всё

@Component
public class ShutdownListener {

@Autowired
private BindingsEndpoint bindingsEndpoint;

@EventListener(ContextClosedEvent.class)
public void onApplicationShutdown() {
// Stop reading more messages from the queue
bindingsEndpoint.changeState("binding-name",State.STOPPED);
// Don't want to do this, but instead wait for the currently processing message to finish
Thread.sleep(10000);
ThisApplication.ctx.close();
}
}
Есть ли в Spring встроенный способ узнать, когда обработка остановлена? Это один из примеров, но у меня также есть другие службы, которые выполняют вызовы БД по таймеру или предоставляют конечные точки другим приложениям для отправки работы. Я надеюсь, что есть какой-то общий способ добиться того, что я ищу. Если нет, то как я могу использовать специальный код, чтобы уведомить приложение о том, что оно выполнено с текущей единицей работы.

Подробнее здесь: https://stackoverflow.com/questions/787 ... it-of-work
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»