GO 的優雅終止姿勢
最近優化了一版程序:用到了 golang 的優雅退出機制。
程序使用 etcd 的election sdk
做高可用選主,需要在節點意外下線的時候,主動去 etcd 卸任 (刪除 10s 租約), 否則已經下線的節點還會被 etcd 認爲是 leader。
所以在這裏,優雅退出是技術剛需。
另外根據《雲原生十二要素方法論》 第 9 條: 快速啓動和優雅終止可最大化健壯性 , 也推薦各位遵守實踐。
Fast startup and shutdown are advocated for a more robust and resilient system.
粗淺的認知方案:捕獲程序的終止信號, 主動去卸任。
標準信號 [1] Linux 支持如下標準信號,第二列指示該信號遵守的標準。
Signal Standard Action Comment
────────────────────────────────────────────────────────────────────────
SIGABRT P1990 Core Abort signal from abort(3)
SIGALRM P1990 Term Timer signal from alarm(2)
SIGBUS P2001 Core Bus error (bad memory access)
SIGCHLD P1990 Ign Child stopped or terminated
SIGCLD - Ign A synonym for SIGCHLD
SIGCONT P1990 Cont Continue if stopped
SIGEMT - Term Emulator trap
SIGFPE P1990 Core Floating-point exception
SIGHUP P1990 Term Hangup detected on controlling terminal
or death of controlling process
SIGILL P1990 Core Illegal Instruction
SIGINFO - A synonym for SIGPWR
SIGINT P1990 Term Interrupt from keyboard
SIGIO - Term I/O now possible (4.2BSD)
SIGIOT - Core IOT trap. A synonym for SIGABRT
SIGKILL P1990 Term Kill signal
SIGLOST - Term File lock lost (unused)
SIGPIPE P1990 Term Broken pipe: write to pipe with no
readers; see pipe(7)
SIGPOLL P2001 Term Pollable event (Sys V);
synonym for SIGIO
SIGPROF P2001 Term Profiling timer expired
SIGPWR - Term Power failure (System V)
SIGQUIT P1990 Core Quit from keyboard
SIGSEGV P1990 Core Invalid memory reference
SIGSTKFLT - Term Stack fault on coprocessor (unused)
SIGSTOP P1990 Stop Stop process
SIGTSTP P1990 Stop Stop typed at terminal
SIGSYS P2001 Core Bad system call (SVr4);
see also seccomp(2)
SIGTERM P1990 Term Termination signal
SIGTRAP P2001 Core Trace/breakpoint trap
SIGTTIN P1990 Stop Terminal input for background process
SIGTTOU P1990 Stop Terminal output for background process
SIGUNUSED - Core Synonymous with SIGSYS
SIGURG P2001 Ign Urgent condition on socket (4.2BSD)
SIGUSR1 P1990 Term User-defined signal 1
SIGUSR2 P1990 Term User-defined signal 2
SIGVTALRM P2001 Term Virtual alarm clock (4.2BSD)
SIGXCPU P2001 Core CPU time limit exceeded (4.2BSD);
see setrlimit(2)
SIGXFSZ P2001 Core File size limit exceeded (4.2BSD);
see setrlimit(2)
SIGWINCH - Ign Window resize signal (4.3BSD, Sun)
其中SIGKILL
,SIGSTOP
信號不能被捕獲、阻塞、忽略。
我們常見的三種終止程序的操作:
1.CTRL+C
實際是發送SIGINT
信號,2.kill pid
的作用是向指定進程發送SIGTERM
信號 (這是 kill 默認發送的信息), 若應用程序沒有捕獲並響應該信號的邏輯,則該信號默認動作是 kill 掉進程,這是終止進程的推薦做法。3.kill -9 pid
則是向指定進程發送SIGKILL
信號,SIGKILL 信號既不能被應用程序捕獲,也不能被阻塞或忽略,
故要達成我們的目的,這裏捕獲 SIGINT
SIGTREM
信號就可滿足需求。
golang 提供signal
包來監聽並反饋收到的信號。
可針對長時間運行的程序,新開協程,持續監聽信號,並插入優雅關閉的代碼。
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
go func() {
select {
case sig:= <-c: {
log.Infof("Got %s signal. Aborting...\n", sig)
eCli.Close() // 利用 etcd election sdk主動卸任
os.Exit(1)
}
}
}()
是不是依舊適配容器?
我們得看 DOCKER 官方docker stop
,docker kill
命令的定義。
docker stop[2]: The main process inside the container will receiver SIGTREM, and after a grace period,SIGKILL .(default grace period =10s)
docker kill[3]:The main process inside the container is sent SIGKILL signal (default), or the signal that is specified with the --signal option
我們常用的 docker stop 命令:向容器內進程發送SIGTREM
信號,10s 後發送SIGKILL
信號,這 10s 時間給了程序做優雅關閉的時機,所以上面代碼的邏輯是能適配容器的。
Ref: 十二要素 App 方法論
引用鏈接
[1]
標準信號: https://www.man7.org/linux/man-pages/man7/signal.7.html
[2]
docker stop: https://docs.docker.com/engine/reference/commandline/stop/
[3]
docker kill: https://docs.docker.com/engine/reference/commandline/kill/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/gHjDBo0xWw51qGqr33cKuQ