Spring Boot 최신 판 우아 한 정지 방법 을 자세히 알 아 보 세 요.
먼저 간단 한 코드 를 주세요.다음 과 같 습 니 다.
@RestController
public class DemoController {
@GetMapping("/demo")
public String demo() throws InterruptedException {
//
Thread.sleep(20 * 1000L);
return "hello";
}
}
데이터 가 이 인터페이스 에서 업무 논 리 를 실행 하 라 고 요청 할 때 서버 에서 전원 이 꺼 져 있 으 면 spring boot 의 기본 상황 은 용기(tomcat 등)를 직접 닫 아서 이 업무 논리 실행 에 실 패 했 습 니 다.일부 업무 장면 에서 데이터 가 일치 하지 않 는 상황 이 발생 하고 사무 논 리 는 스크롤 백 되 지 않 습 니 다.오픈 소스 항목:
분산 식 모니터링(Gitee GVP 의 가장 가치 있 는 오픈 소스 프로젝트):https://gitee.com/sanjiankethree/cubic
카메라 영상 흐름 채집:https://gitee.com/sanjiankethree/cubic-video
우아 한 정지
현재 Spring Boot 는 2.3.4.RELEASE 까지 발 전 했 고 2.3 버 전이 도래 함 에 따라 우아 한 정지 체제 도 더욱 완선 되 었 다.
현재 버 전의 Spring Boot 우아 한 정지 지원 Jetty,Reactor Netty,Tomcat,Undertow 및 반응 식 및 Servlet 기반 웹 프로그램 은 우아 한 정지 기능 을 지원 합 니 다.
우아 한 정지 의 목적:
우아 한 정지 가 없 으 면 서버 가 직접 닫 습 니 다(kill-9).그러면 현재 용기 에서 실행 중인 업무 가 직접 실패 하고 특정한 특수 한 장면 에서 더러 운 데 이 터 를 만 들 수 있 습 니 다.
우아 한 정지 설정 이 추 가 된 후:
서버 가 종료(kill-2)를 실행 할 때 용기 내부 업무 스 레 드 가 실 행 될 시간 을 조금 남 깁 니 다.이 때 용기 도 새로운 요청 이 들 어 갈 수 없습니다.새로운 요청 의 처리 방식 은 웹 서버 와 관련 이 있 으 며,Reactor Netty,Tomcat 은 접속 요청 을 중단 합 니 다.Undertow 의 처리 방식 은 503 으로 되 돌아 갑 니 다.
새 버 전 설정
YAML 설정
새 버 전 설정 은 매우 간단 합 니 다.server.shutdown=graceful 이면 됩 니 다.(주의,우아 한 정지 설정 은 Tomcat 9.0.33(포함)이상 버 전에 맞 춰 야 합 니 다.)
server:
port: 6080
shutdown: graceful #
spring:
lifecycle:
timeout-per-shutdown-phase: 20s # 30s
버퍼 파라미터 timeout-per-shutdown-phase 를 설정 한 후 정 해진 시간 내 에 스 레 드 가 실행 되 지 않 으 면 강제로 정지 합 니 다.다음은 정지 할 때 우아 한 정지 로그 와 추가 하지 않 는 차 이 를 살 펴 보 겠 습 니 다.
//
Disconnected from the target VM, address: '127.0.0.1:49754', transport: 'socket'
Process finished with exit code 130 (interrupted by signal 2: SIGINT)
우아 한 정지 설정 을 추가 하면 로그 Waiting for active requests to cpmplete 를 뚜렷하게 발견 할 수 있 습 니 다.이 때 용 기 는 Shutdown Hook 이 실 행 된 후에 중 단 됩 니 다.닫 기 방식
1.kill-9 동작 을 사용 하지 말고 kill-2 를 사용 하여 용 기 를 닫 습 니 다.이렇게 해야만 자바 내부 Shutdown Hook 작업 을 촉발 할 수 있 습 니 다.kill-9 는 Shutdown Hook 을 촉발 하지 않 습 니 다.
2.터미널 모니터링 POST 요청/actuator/shutdown 을 사용 하여 우아 하 게 전원 을 끌 수 있 습 니 다.
ShutdownHook 추가
위의 로 그 를 통 해 우 리 는 Druid 가 자신의 Shutdown Hook 을 실행 한 것 을 발 견 했 습 니 다.그러면 우 리 는 Shutdown Hook 을 추가 합 니 다.몇 가지 간단 한 방법 이 있 습 니 다.
1.DisposableBean 인 터 페 이 스 를 실현 하고 destroy 방법 실현
@Slf4j
@Service
public class DefaultDataStore implements DisposableBean {
private final ExecutorService executorService = new ThreadPoolExecutor(OSUtil.getAvailableProcessors(), OSUtil.getAvailableProcessors() + 1, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(200), new DefaultThreadFactory("UploadVideo"));
@Override
public void destroy() throws Exception {
log.info(" DisposableBean");
executorService.shutdown();
}
}
2,사용@PreDestroy 주해
@Slf4j
@Service
public class DefaultDataStore {
private final ExecutorService executorService = new ThreadPoolExecutor(OSUtil.getAvailableProcessors(), OSUtil.getAvailableProcessors() + 1, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(200), new DefaultThreadFactory("UploadVideo"));
@PreDestroy
public void shutdown() {
log.info(" @PreDestroy");
executorService.shutdown();
}
}
여기 주의,@PreDestroy 가 DisposableBean 보다 먼저 실 행 됩 니 다.폐쇄 원리
1、kill pid 를 사용 하여 닫 습 니 다.원본 코드 는 간단 합 니 다.GracefulShutdown 을 보 실 수 있 습 니 다.
private void doShutdown(GracefulShutdownCallback callback) {
List<Connector> connectors = getConnectors();
connectors.forEach(this::close);
try {
for (Container host : this.tomcat.getEngine().findChildren()) {
for (Container context : host.findChildren()) {
while (isActive(context)) {
if (this.aborted) {
logger.info("Graceful shutdown aborted with one or more requests still active");
callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE);
return;
}
Thread.sleep(50);
}
}
}
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
logger.info("Graceful shutdown complete");
callback.shutdownComplete(GracefulShutdownResult.IDLE);
}
2.터미널 모니터링 POST 요청/actuator/shutdown 종료 사용actuator 는 모두 SPI 의 확장 방식 을 사 용 했 기 때문에 AutoConfiguration 을 살 펴 보면 관건 은 Shutdown Endpoint 입 니 다.
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnAvailableEndpoint(
endpoint = ShutdownEndpoint.class
)
public class ShutdownEndpointAutoConfiguration {
public ShutdownEndpointAutoConfiguration() {
}
@Bean(
destroyMethod = ""
)
@ConditionalOnMissingBean
public ShutdownEndpoint shutdownEndpoint() {
return new ShutdownEndpoint();
}
}
Shutdown Endpoint,편폭 을 절약 하기 위해 중요 한 것 만 남 겼 습 니 다.
@Endpoint(
id = "shutdown",
enableByDefault = false
)
public class ShutdownEndpoint implements ApplicationContextAware {
@WriteOperation
public Map<String, String> shutdown() {
if (this.context == null) {
return NO_CONTEXT_MESSAGE;
} else {
boolean var6 = false;
Map var1;
try {
var6 = true;
var1 = SHUTDOWN_MESSAGE;
var6 = false;
} finally {
if (var6) {
Thread thread = new Thread(this::performShutdown);
thread.setContextClassLoader(this.getClass().getClassLoader());
thread.start();
}
}
Thread thread = new Thread(this::performShutdown);
thread.setContextClassLoader(this.getClass().getClassLoader());
thread.start();
return var1;
}
}
private void performShutdown() {
try {
Thread.sleep(500L);
} catch (InterruptedException var2) {
Thread.currentThread().interrupt();
}
this.context.close(); //
}
}
this.context.close()를 호출 했 습 니 다.사실은 AbstractApplication Context 의 close()방법 입 니 다.(중점 은 doClose()입 니 다.)
/**
* Close this application context, destroying all beans in its bean factory.
* <p>Delegates to {@code doClose()} for the actual closing procedure.
* Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
* @see #doClose()
* @see #registerShutdownHook()
*/
@Override
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose(); // : bean jvm shutdown hook
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
후기여기까지
버 전의 Spring Boot 우아 정지 에 대해 서 는 말 이 끝났다.왜
라 고 했 어 요?닫 을 때 서버 내부 스 레 드 의 실행 이 완료 되 었 을 뿐 호출 자의 상 태 는 관심 이 없다 는 것 을 알 수 있 기 때문이다.Dubbo 든 Cloud 의 분포 식 서비스 프레임 워 크 든 서비스 가 중단 되 기 전에 공급 자 를 등록 센터 에서 반 등록 한 다음 에 서비스 제공 자 를 정지 시 켜 야 업무 시스템 이 각종 503,timeout 등 현상 이 발생 하지 않도록 확보 할 수 있다.
다행히 현재 Spring Boot 는 Kubernetes 와 결합 하여 이 점 을 해결 해 주 었 습 니 다.즉,Spring Boot 2.3 버 전의 새로운 기능 인 Liveness(생존 상태)와 Readiness(준비 상태)입 니 다.
간단하게 이 두 상 태 를 제시 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.