본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로프로그래밍 › Java › 동시성

[링크]셧다운 후크를 사용한 어플리케이션의 안전한 종료 처리

목차

http://javacan.tistory.com/entry/86

셧다운 훅을 이용한 종료 처리에 관한 외부 글 링크다. 원문의 예제와 실행 환경은 링크에서 확인한다.

자바의 셧다운 훅은 JVM이 정상적인 종료 절차에 들어갈 때 실행할 작업을 등록하는 방법이다. 열려 있는 리소스를 닫거나 진행 중인 작업을 짧게 정리하는 용도로 사용한다. 강제 종료나 전원 장애에서는 실행이 보장되지 않으므로 데이터 보존을 훅 하나에만 맡기면 안 된다. 긴 작업을 훅에서 기다리면 애플리케이션 종료가 지연될 수 있다.

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    System.out.println("종료 정리 시작");
    // 종료 가능한 리소스를 닫는다.
}));

훅 안에서 새 요청을 받거나 끝나지 않는 작업을 시작하지 않는다. 여러 훅 사이의 실행 순서는 보장되지 않으므로 특정 훅이 다른 훅보다 먼저 실행된다고 가정해서도 안 된다. 서버 프레임워크가 제공하는 종료 생명주기 기능이 있다면 그 경로로 자원을 정리하는 것이 관리하기 쉽다.

종료 훅의 호출 조건과 범위

Runtime.addShutdownHook은 시작하지 않은 Thread를 JVM 종료 시 실행하도록 등록한다. 정상적인 System.exit, 마지막 일반 스레드 종료, 처리 가능한 종료 신호 같은 상황에서 실행될 수 있다. 반면 강제 프로세스 종료, JVM 충돌, 전원 차단에서는 훅 실행을 기대할 수 없다. 따라서 파일의 중요한 상태는 평소 작업 흐름에서 안전하게 저장하고, 훅은 최종 정리 용도로 쓴다.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

ExecutorService workers = Executors.newFixedThreadPool(2);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    workers.shutdown();
    try {
        if (!workers.awaitTermination(5, TimeUnit.SECONDS)) {
            workers.shutdownNow();
        }
    } catch (InterruptedException e) {
        workers.shutdownNow();
        Thread.currentThread().interrupt();
    }
}));

훅은 새 작업 접수를 먼저 막고, 진행 중인 작업이 끝나길 제한된 시간만 기다린다. shutdownNow()는 작업 스레드에 인터럽트를 요청하지만 강제 중단을 보장하지는 않는다. 작업 코드가 인터럽트에 반응하도록 만들어야 한다. 예제의 5초는 설명용 한도이므로 서버의 종료 유예 시간과 데이터 정합성 요구에 맞춰 정한다. JVM은 등록된 훅들을 순서 보장 없이 병렬로 시작할 수 있으므로 한 훅이 다른 훅의 결과를 기다리는 의존성은 피한다. 종료 작업에서 오류가 나더라도 다른 자원 정리까지 진행할 수 있도록 로그와 예외 경계를 설계한다.

참고: Oracle Runtime.addShutdownHook API

같은 카테고리의 글