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支持如下标准信号,第二列指示该信号遵守的标准。
SignalStandardActionComment────────────────────────────────────────────────────────────────────────SIGABRTP1990CoreAbortsignalfromabort(3)SIGALRMP1990TermTimersignalfromalarm(2)SIGBUSP2001CoreBuserror(badmemoryaccess)SIGCHLDP1990IgnChildstoppedorterminatedSIGCLD-IgnAsynonymforSIGCHLDSIGCONTP1990ContContinueifstoppedSIGEMT-TermEmulatortrapSIGFPEP1990CoreFloating-pointexceptionSIGHUPP1990TermHangupdetectedoncontrollingterminalordeathofcontrollingprocessSIGILLP1990CoreIllegalInstructionSIGINFO-AsynonymforSIGPWRSIGINTP1990TermInterruptfromkeyboardSIGIO-TermI/Onowpossible(4.2BSD)SIGIOT-CoreIOTtrap.AsynonymforSIGABRTSIGKILLP1990TermKillsignalSIGLOST-TermFilelocklost(unused)SIGPIPEP1990TermBrokenpipe:writetopipewithnoreaders;seepipe(7)SIGPOLLP2001TermPollableevent(SysV);synonymforSIGIOSIGPROFP2001TermProfilingtimerexpiredSIGPWR-TermPowerfailure(SystemV)SIGQUITP1990CoreQuitfromkeyboardSIGSEGVP1990CoreInvalidmemoryreferenceSIGSTKFLT-TermStackfaultoncoprocessor(unused)SIGSTOPP1990StopStopprocessSIGTSTPP1990StopStoptypedatterminalSIGSYSP2001CoreBadsystemcall(SVr4);seealsoseccomp(2)SIGTERMP1990TermTerminationsignalSIGTRAPP2001CoreTrace/breakpointtrapSIGTTINP1990StopTerminalinputforbackgroundprocessSIGTTOUP1990StopTerminaloutputforbackgroundprocessSIGUNUSED-CoreSynonymouswithSIGSYSSIGURGP2001IgnUrgentconditiononsocket(4.2BSD)SIGUSR1P1990TermUser-definedsignal1SIGUSR2P1990TermUser-definedsignal2SIGVTALRMP2001TermVirtualalarmclock(4.2BSD)SIGXCPUP2001CoreCPUtimelimitexceeded(4.2BSD);seesetrlimit(2)SIGXFSZP2001CoreFilesizelimitexceeded(4.2BSD);seesetrlimit(2)SIGWINCH-IgnWindowresizesignal(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(chanos.Signal)signal.Notify(c,syscall.SIGTERM,syscall.SIGINT)gofunc(){select{casesig:=<-c:{log.Infof("Got%ssignal.Aborting...\n",sig)eCli.Close()//利用etcdelectionsdk主动卸任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/
有态度的马甲建立了真●高质量交流群:大佬汇聚、无事静默、有事激活、深度思考。
[长按图片加我好友]
年终总结:2021技术文大盘点 | 打包过去,面向未来
项目总结:麻雀虽小,五脏俱全
理念总结:实话实说:只会.NET,会让我们一直处于鄙视链、食物链的下游
云原生系列:什么是云原生?
点“赞”戳“在看”
体现态度很有必要!
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...