[Linux] Graceful Shutdown

Graceful Shutdown์€ ๋ฒˆ์—ญํ•˜์ž๋ฉด "์šฐ์•„ํ•œ ์ค‘๋‹จ"์œผ๋กœ, ์•ˆ์ •์ ์ธ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค๋•Œ ์ค‘์š”ํ•œ ํ•ต์‹ฌ ์›์น™ ์ค‘ ํ•˜๋‚˜๋‹ค.

Graceful Shutdown์˜ ๊ธฐ๋ณธ ์›๋ฆฌ๋Š” ๋Œ€๋žต 2๊ฐ€์ง€ ์ •๋„๊ฐ€ ์žˆ๋‹ค.

  1. shutdown์ด ์‹œ์ž‘๋˜๋ฉด ๋” ์ด์ƒ์˜ ์š”์ฒญ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.

  2. shutdown์ด ์‹œ์ž‘๋˜์—ˆ๋”๋ผ๋„, ์ด๋ฏธ ๋ฐ›์€ ์š”์ฒญ์€ ๋‹ค ์ฒ˜๋ฆฌํ•˜๊ณ  ์ข…๋ฃŒํ•œ๋‹ค.



์ด๋ฅผ ํ†ตํ•ด์„œ ๋ญ”๊ฐ€ ์ด๋„ ์ €๋„ ์•„๋‹Œ ์ƒํƒœ๋กœ ์ž‘์—…์ด ๋Š๊ธฐ๋Š” ํ˜„์ƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์„ ์ฃผ์•ˆ์ ์œผ๋กœ ์‚ผ๋Š”๋‹ค.
์ด์— ๋Œ€ํ•œ ๊ณ ๋ ค ์—†์ด ์‹œ์Šคํ…œ์„ ๋งŒ๋“ ๋‹ค๋ฉด, ์˜จ์ „ํ•˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์†์ƒ๋˜๊ธฐ ์‰ฝ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋งค ํƒœ์Šคํฌ๋งˆ๋‹ค A->B->C 3๊ฐœ์˜ ์ž‘์—…์„ ํ•ด์•ผํ•˜๋Š”๋ฐ, B๊นŒ์ง€๋งŒ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ค‘๋‹จ๋˜์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.

Graceful Shutdown์€ ์ด๋Ÿฌํ•œ ์‚ฌํƒœ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ ์‹ ํ˜ธ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ง€ํ•ด์„œ ์ ์ •ํ•œ ์Šคํ…์—์„œ ๋ฉˆ์ถ”๋„๋ก ์œ ๋„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก ์ด๋‹ค.




์›๋ฆฌ์™€ ์ œํ•œ์‚ฌํ•ญ

Graceful Shutdown์˜ ์›๋ฆฌ์™€ ์ œํ•œ์„ ์•Œ๋ ค๋ฉด Linux์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋„ ์–ด๋А ์ •๋„ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ผ๋‹จ ์ ์ ˆํ•˜๊ฒŒ Graceful Shutdown ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•˜๋”๋ผ๋„, ๋ชจ๋“  ์ƒํ™ฉ์—์„œ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

Linux์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ์‹ ํ˜ธ์—๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ ํฌ๊ฒŒ 3๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  1. SIGTERM: ์ •์ƒ ์ข…๋ฃŒ. ํ”„๋กœ์„ธ์Šค์—๊ฒŒ ์ข…๋ฃŒ ์š”์ฒญ ์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ธ๋‹ค. ๋ช‡ ์ดˆ ์ •๋„์˜ ์œ ์˜ˆ์‹œ๊ฐ„์„ ์ฃผ๊ณ , ์•Œ์•„์„œ ์ •๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด OS๊ฐ€ ๊ฐ•์ œ๋กœ ์ค‘๋‹จ์‹œํ‚จ๋‹ค.

  2. SIGINT: ์ •์ƒ ์ข…๋ฃŒ. Ctrl+C๋ฅผ ํ˜ธ์ถœํ–ˆ์„๋•Œ ์ฃผ๋กœ ๋‚ ๋ผ๊ฐ„๋‹ค. ์ด๊ฒƒ๋„ SIGTERM๊ณผ ๋™์ž‘ ์›๋ฆฌ๋Š” ๋น„์Šทํ•˜๋‹ค.

  3. SIGKILL: ๋น„์ •์ƒ ์ข…๋ฃŒ. ๋ฐ”๋กœ ์ค‘๋‹จ์‹œํ‚จ๋‹ค.



์—ฌ๊ธฐ์„œ SIGTERM์ด๋‚˜ SIGINT๋Š” ์œ ์˜ˆ์‹œ๊ฐ„์ด ์žˆ๊ธฐ์— ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ์ž‘์—…์„ ์–ด๋А ์ •๋„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, SIGKILL์˜ ๊ฒฝ์šฐ์—๋Š” ๊ทธ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ฐ€๋” ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒํ• ๋•Œ kill -9๋กœ ์ค‘๋‹จ ๋ช…๋ น์„ ๋‚ ๋ฆฐ ๊ธฐ์–ต์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๊ฒŒ SIGKILL์ด๋‹ค.
๋‹น์‹ ์€ ๋ญ”๊ฐ€ ์ •๋ฆฌํ•  ์‹œ๊ฐ„๋„ ์ฃผ์ง€ ์•Š๊ณ  ์ฃฝ์—ฌ๋ฒผ๋ฆฐ ๊ฒƒ์ด๋‹ค.
SIGTERM์€ kill -15๋ฅผ ์จ์•ผ ํ•œ๋‹ค.

https://linuxhandbook.com/sigterm-vs-sigkill/
์•ž์œผ๋กœ๋Š” ๋ช‡์ดˆ ์ •๋„ ๊ธฐ๋‹ค๋ ค์ฃผ๋Š” ์—ฌ์œ ๋ฅผ ๊ฐ€์ ธ๋ณด์ž




SIGINT, SIGTERM ํ•ธ๋“ค๋งํ•ด๋ณด๊ธฐ (with Rust)

๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ Graceful Shutdown์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์„ ๋ณด์—ฌ๋ณด๊ฒ ๋‹ค.
์•„๋ž˜์™€ ๊ฐ™์€ ์Šคํ…์„ ๋ฐ˜๋ณตํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

์—ฌ๊ธฐ์„œ A-B-C๋Š” ํ•˜๋‚˜์˜ ์™„์ „ํ•œ ์ž‘์—…์ด๋‹ค.
๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ 


์• ๋งคํ•œ ์ง€์ ์—์„œ ์ข…๋ฃŒ ์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ด๋ฉด ์ด๋„์ €๋„ ์•„๋‹Œ ์ƒํƒœ์—์„œ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ๋‹ค.

์ด๊ฑธ ํ•ธ๋“ค๋งํ•˜๋ ค๋ฉด SIGINT์™€ SIGTERM ์‹ ํ˜ธ๋ฅผ catchํ•ด์„œ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
์—ฌ๊ธฐ์„œ๋Š” signal-hook๋ผ๋Š” ์ „์šฉ crate๋ฅผ ํ†ตํ•ด์„œ ๊ฐ„๋‹จํ•œ ์ œ์–ด ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ๋‹ค.

use std::{
    process::exit,
    sync::{atomic::AtomicBool, Arc},
    thread::sleep,
    time::Duration,
};

fn main() {
    let sigterm = Arc::new(AtomicBool::new(false));
    let sigint = Arc::new(AtomicBool::new(false));

    signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&sigterm)).unwrap();
    signal_hook::flag::register(signal_hook::consts::SIGINT, Arc::clone(&sigint)).unwrap();

    let mut count = 0;
    loop {
        if sigterm.load(std::sync::atomic::Ordering::Relaxed) {
            println!("SIGTERM received");
            exit(0);
        }

        if sigint.load(std::sync::atomic::Ordering::Relaxed) {
            println!("SIGINT received");
            exit(0);
        }

        println!("A: {count}");
        sleep(Duration::from_secs(1));

        println!("B: {count}");
        sleep(Duration::from_secs(1));

        println!("C: {count}");
        sleep(Duration::from_secs(1));

        count += 1;
    }
}

๊ฐ๊ฐ์˜ ํ”Œ๋ž˜๊ทธ์šฉ atomic ๋ณ€์ˆ˜๋ฅผ ๋‘๊ณ , SIG๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ทธ๊ฑธ catchํ•ด์„œ ์ €์žฅํ•˜๋„๋ก ํ–ˆ๋‹ค.
์ด๋Ÿฌ๋ฉด ๋‚ด๋ถ€์—์„œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ปค์Šคํ…€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ์ค‘๋‹จ๋˜์ง€ ์•Š๊ณ , ํ”„๋กœ๊ทธ๋žจ ์ˆ˜์ค€์—์„œ ์ข…๋ฃŒ ์‹œ์ ์„ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ• ๊ฑฐ ๋‹คํ•˜๊ณ  exit ๋‚ ๋ ค์„œ ์ข…๋ฃŒํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ ์ด์ œ

๋ฐ”๋กœ ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ณ  ํ•œ ์Šคํ… ๋‹ค ๊ธฐ๋‹ค๋ฆฐ ๋‹ค์Œ์— ์ข…๋ฃŒ๋  ๊ฒƒ์ด๋‹ค.




Java SpringBoot์˜ ๊ฒฝ์šฐ

Spring์ฒ˜๋Ÿผ ์–ด๋А์ •๋„ ์™„์„ฑ๋œ ํ˜•ํƒœ์˜ ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์€ ์ž์ฒด์ ์œผ๋กœ Graceful Shutdown์— ๋Œ€ํ•œ ์˜ต์…˜์„ ์ œ๊ณตํ•œ๋‹ค. ๊ทธ๋ƒฅ ์œ„์—์„œ ์„ค๋ช…ํ•œ๊ฑธ ํ”Œ๋ž˜๊ทธ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ์ ์šฉ๋˜๋„๋ก ํ•ด๋‘” ๊ฒƒ์ด๋‹ค.

application properties์— ์ด๊ฒƒ๋งŒ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

server:
  shutdown: graceful

SpringBoot 2.3๋ถ€ํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.