Эта статья является оригинальной статьей. Любая форма перепечатки приветствуется, но обязательно с указанием источникаЛенг Ленг https://lltx.github.io.
Что такое изящное завершение работы
Начнем с простого кода, а именно:
@RestController
public class DemoController {
@GetMapping("/demo")
public String demo() throws InterruptedException {
// 模拟业务耗时处理流程
Thread.sleep(20 * 1000L);
return "hello";
}
}
Когда наш трафик запрашивает этот интерфейс для выполнения бизнес-логики, если сервер в это время выполняет завершение работы (kill), spring boot по умолчанию напрямую отключает контейнер (tomcat и т. д.), что приводит к сбою выполнения этой бизнес-логики. . В некоторых бизнес-сценариях: будут несогласованности данных, и логика транзакций не будет откатана.
graceful shutdown
В последней версии spring boot 2.3 эта функция встроена, и для ее обработки нет необходимости расширять пул потоков контейнера. В настоящее время встроенные поддерживаемые веб-серверы Spring Boot (Jetty, Reactor Netty, Tomcat и Undertow), а также реактивные веб-приложения и веб-приложения на основе сервлетов поддерживают плавное завершение работы. Давайте посмотрим, как использовать:
когда используешьserver.shutdown=graceful
Если этот параметр включен, при завершении работы веб-контейнера веб-сервер больше не будет получать новые запросы и будет ждать буферного периода для завершения активных запросов.
Опыт настройки
Поддерживаемое здесь поведение завершения работы, давайте посмотрим на перечисление исходного кода следующим образом:
/**
* Configuration for shutting down a {@link WebServer}.
*
* @author Andy Wilkinson
* @since 2.3.0
*/
public enum Shutdown {
/**
* 优雅停机 (限期停机)
*
*/
GRACEFUL,
/**
* 立即停机
*/
IMMEDIATE;
}
буферный периодtimeout-per-shutdown-phase
настроить
- Время по умолчанию 30 с, что означает максимальное время ожидания 30 с. Тайм-аут будет остановлен независимо от того, выполняется ли задача потока или нет. Он должен быть установлен разумно и разумно.
Опыт эффекта
-
- интерфейс сервера запросов
-
- выполнить закрытие приложения
-
- Сервер получает команду выключения
2020-05-17 18:28:28.940 INFO 60341 --- [extShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
2020-05-17 18:28:45.923 INFO 60341 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete
-
- Выполнение запроса интерфейса завершено
связанная информация
- о казни здесьkill -2вместоkill -9
- kill -2 эквивалентен сочетанию клавиш Ctrl + C, которое запускает обработку событий Java ShutdownHook (для корректного завершения работы или некоторой постобработки обратитесь к следующему исходному коду)
//ApplicationContext
@Override
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
- kill -9, насильственная эстетика принудительно завершает процесс, ShutdownHook не выполняется
- Мягкое завершение работы с активацией конечных точек
POST-запрос/actuator/shutdownМожет быть выполнено изящное завершение работы.
Анализ исходного кода
@Endpoint(id = "shutdown", enableByDefault = false)
public class ShutdownEndpoint implements ApplicationContextAware {
@WriteOperation
public Map<String, String> shutdown() {
Thread thread = new Thread(this::performShutdown);
thread.setContextClassLoader(getClass().getClassLoader());
thread.start();
}
private void performShutdown() {
try {
Thread.sleep(500L);
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
// 此处close 逻辑和上边 shutdownhook 的处理一样
this.context.close();
}
}
- Различия в корректном завершении работы различных веб-контейнеров
Поведение контейнера во время простоя зависит от конкретного поведения веб-контейнера.
имя веб-контейнера | заявление о поведении |
---|---|
tomcat 9.0.33+ | Перестать получать запросы, клиент ждет тайм-аут для новых запросов. |
Reactor Netty | Перестать получать запросы, клиент ждет тайм-аут для новых запросов. |
Undertow | Перестаньте получать запросы, и клиент напрямую вернет 503 для новых запросов. |