스프링 부트 정상 종료
내장된 Tomcat에서 지원하는 Spring Boot 애플리케이션을 개발 중이며 다음 단계로 정상 종료를 개발해야 합니다.
- 새 HTTP 요청 처리 중지(웹 컨테이너 중지)
- 이미 수락된 모든 요청 처리
- Spring 응용 프로그램 종료 컨텍스트
*위 단계를 순차적으로 수행(하나씩)
어떻게 하면 이를 달성할 수 있을까요?
추신: 스프링 부트 1.5.20.릴리스, Java 8
정상 종료 지원은 Spring Boot 2.3(2020년 5월 출시)에 추가되었습니다.이렇게 하면 컨텍스트를 닫고 컨테이너를 종료하기 전에 활성 요청을 완료할 수 있습니다.
정상 종료를 사용하도록 설정하면 종료 시 응용 프로그램이 다음 단계를 순차적으로 수행합니다.
- 새 요청 수락 중지
- 이미 수락된 요청을 처리하기 위해 구성 가능한 시간을 기다립니다.
- 정지 용기
- 내장된 서버 중지
릴리스 정보에서:
정상 종료는 4개의 내장 웹 서버(Jetty, Reactor Netty, Tomcat 및 언더도우)와 반응형 및 서블릿 기반 웹 애플리케이션 모두에서 지원됩니다.사용하여 활성화할 경우
server.shutdown=graceful
종료 시 웹 서버는 더 이상 새 요청을 허용하지 않으며 활성 요청이 완료될 때까지 유예 기간을 기다립니다.유예 기간은 다음을 사용하여 구성할 수 있습니다.spring.lifecycle.timeout-per-shutdown-phase
.
- 정상 종료를 사용하려면 다음과 같이 추가합니다.
server.shutdown=graceful
속성으로(기본값으로 설정됨)immediate
). - 유예 기간은 다음을 사용하여 구성할 수 있습니다.
spring.lifecycle.timeout-per-shutdown-phase
속성(예:spring.lifecycle.timeout-per-shutdown-phase=1m
.
Spring Boot < 2.3의 경우, 이번 Spring GitHub 호에서 설명한 바와 같이 서버의 커넥터를 수정하여 새로운 요청 수락을 중지합니다.
저는 다음과 같은 결과를 얻었습니다.
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.catalina.connector.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
public class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
private static final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);
private volatile Connector connector;
@Override
public void customize(Connector connector) {
this.connector = connector;
}
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
log.info("Protocol handler is shutting down");
this.connector.pause();
Executor executor = this.connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor) {
try {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown();
if (!threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS))
log.warn("Tomcat thread pool did not shut down gracefully within 30 seconds. Proceeding with forceful shutdown");
else
log.info("Protocol handler shut down");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
더 많은 콩:
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
...
@Bean
public GracefulShutdown gracefulShutdown() {
return new GracefulShutdown();
}
@Bean
public EmbeddedServletContainerFactory servletContainer(final GracefulShutdown gracefulShutdown) {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addConnectorCustomizers(gracefulShutdown);
return factory;
}
...
심플한 스프링 부츠 자체가 기능을 제공합니다.https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ #boot-message-application-message
void shoutdown(){
System.out.println("====+= Shoutdown +++===");
System.exit(SpringApplication.exit(apc, this.exitCodeGenerator()));
}
출력에서 모든 현재 스레드가 닫혀 있는 것을 볼 수 있습니다.출력:
소리쳐 +++===
2020-06-09 11:21:45,543
DEBUG[main][c.u.j.c.EnableEncryptablePropertiesBeanFactoryPostProcessor]
Application Event Raised: ExitCodeEvent 2020-06-09 11:21:45,543
DEBUG[main][c.u.j.c.EnableEncryptablePropertiesBeanFactoryPostProcessor]
Application Event Raised: ExitCodeEvent 2020-06-09 11:21:45,546
DEBUG[main][c.u.j.c.EnableEncryptablePropertiesBeanFactoryPostProcessor]
Application Event Raised: ContextClosedEvent 2020-06-09 11:21:45,546
DEBUG[main][c.u.j.c.EnableEncryptablePropertiesBeanFactoryPostProcessor]
Application Event Raised: ContextClosedEvent 2020-06-09 11:21:45,547
INFO [main][o.a.kafka.clients.producer.KafkaProducer] [Producer
clientId=producer-1] Closing the Kafka producer with timeoutMillis =
30000 ms. 2020-06-09 11:21:45,548
DEBUG[kafka-producer-network-thread |
producer-1][o.a.k.clients.producer.internals.Sender] [Producer
clientId=producer-1] Beginning shutdown of Kafka producer I/O thread,
sending remaining records. 2020-06-09 11:21:45,551
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name connections-closed: 2020-06-09 11:21:45,554
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name connections-created: 2020-06-09 11:21:45,554
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name successful-authentication: 2020-06-09 11:21:45,558
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name failed-authentication: 2020-06-09 11:21:45,558
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name bytes-sent-received: 2020-06-09 11:21:45,559
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name bytes-sent: 2020-06-09 11:21:45,559
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name bytes-received: 2020-06-09 11:21:45,560
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name select-time: 2020-06-09 11:21:45,561
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name io-time: 2020-06-09 11:21:45,570
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name node--1.bytes-sent 2020-06-09 11:21:45,570
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name node--1.bytes-received 2020-06-09 11:21:45,570
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name node--1.latency 2020-06-09 11:21:45,571
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name node-0.bytes-sent 2020-06-09 11:21:45,571
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name node-0.bytes-received 2020-06-09 11:21:45,573
DEBUG[kafka-producer-network-thread |
producer-1][org.apache.kafka.common.metrics.Metrics] Removed sensor
with name node-0.latency 2020-06-09 11:21:45,573
DEBUG[kafka-producer-network-thread |
producer-1][o.a.k.clients.producer.internals.Sender] [Producer
clientId=producer-1] Shutdown of Kafka producer I/O thread has
completed. 2020-06-09 11:21:45,607
DEBUG[main][o.a.kafka.clients.producer.KafkaProducer] [Producer
clientId=producer-1] Kafka producer has been closed 2020-06-09
11:21:45,611 DEBUG[main][o.hibernate.internal.SessionFactoryImpl]
HHH000031: Closing 2020-06-09 11:21:45,611
DEBUG[main][o.h.type.spi.TypeConfiguration$Scope] Un-scoping
TypeConfiguration
[org.hibernate.type.spi.TypeConfiguration$Scope@5dfd31f4] from
SessionFactory [org.hibernate.internal.SessionFactoryImpl@62a54948]
2020-06-09 11:21:45,612
DEBUG[main][o.h.s.i.AbstractServiceRegistryImpl] Implicitly
destroying ServiceRegistry on de-registration of all child
ServiceRegistries 2020-06-09 11:21:45,613
DEBUG[main][o.h.b.r.i.BootstrapServiceRegistryImpl] Implicitly
destroying Boot-strap registry on de-registration of all child
ServiceRegistries 2020-06-09 11:21:45,613 INFO
[main][com.zaxxer.hikari.HikariDataSource] HikariPool-1 - Shutdown
initiated... 2020-06-09 11:21:45,754 INFO
[main][com.zaxxer.hikari.HikariDataSource] HikariPool-1 - Shutdown
completed.
언급URL : https://stackoverflow.com/questions/56040542/spring-boot-graceful-shutdown
'programing' 카테고리의 다른 글
phpMyAdmin을 사용하여 기본 빈 공간이 있는 Null 값 필드에 대한 ods 파일을 가져오는 방법 (0) | 2023.09.04 |
---|---|
PowerShell 및 프로세스 종료 코드 (0) | 2023.08.30 |
외부 키 참조를 업데이트하지 않고 InnoDB 테이블의 이름을 변경하시겠습니까? (0) | 2023.08.30 |
jQuery Ajax 게시 요청이 Chrome에서 보류 중인 상태로 고착 (0) | 2023.08.30 |
텍스트 편집에서 선 색상을 변경하는 방법 (0) | 2023.08.30 |