GO的优雅终止姿势

简介: 最近优化了一版程序:用到了golang的优雅退出机制。

最近优化了一版程序:用到了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信号既不能被应用程序捕获,也不能被阻塞或忽略,


故要达成我们的目的,这里捕获 SIGINTSIGTREM信号就可满足需求。


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时间给了程序做优雅关闭的时机,所以上面代码的逻辑是能适配容器的。

目录
打赏
0
0
0
0
11
分享
相关文章
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
31853 78
如何保证分布式文件系统的数据一致性
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局(上)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局
17655 18
灵骏可预期网络:Built for AI Infrastructure
通用人工智能离我们越来越近,全世界的关注和投入正在带来日新“周”异的变化。回顾人工智能的诞生和发展历程,人类计算能力的进步几乎牵动了每一次的重大技术突破,当前的大模型热潮更是如此,只是动辄千万亿参数级的模型体量,所需计算资源远超单颗芯片的上限,超大规模的计算集群成为支撑技术发展和应用创新的关键基础设施。面向智能:云基础设施网络技术面临新挑战如何突破单个芯片、单个服务器节点的算力上限,在超大规模情况
31193 10
灵骏可预期网络:Built for AI Infrastructure
设计模式(C++版)
看懂UML类图和时序图30分钟学会UML类图设计原则单一职责原则定义:单一职责原则,所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。bad case:IPhone类承担了协议管理(Dial、HangUp)、数据传送(Chat)。good case:里式替换原则定义:里氏代换原则(Liskov 
36193 19
设计模式(C++版)
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
24468 14
重生之---我测阿里云U1实例(通用算力型)
阿里云产品全线降价的一力作,2023年4月阿里云推出新款通用算力型ECS云服务器Universal实例,该款服务器的真实表现如何?让我先测为敬!
36515 15
重生之---我测阿里云U1实例(通用算力型)
为笔记本更换固态硬盘的方法
本文介绍为笔记本电脑拆机、更换固态硬盘的具体方法~
18011 41
为笔记本更换固态硬盘的方法
Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务
随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。
29747 52
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等