Go语言中文网,每天致力于分享编码知识,欢迎关注我,会有意想不到的收获!   

  

     

  

  

01 写在前面      

  按照一般的设计原则,每一个HTTP请求都是无状态的,所以大多数情况下,Web应用很容易横向伸缩。“无状态”还意味着HTTP请求发起和重试的成本很低,这使得Web界面的开发很少关注优雅挂起(部分原因是Web框架考虑到了这部分)。   

  

  但是,业务中总会有对暂停敏感的接口(比如支付相关的),总会有一些带状态的服务。这个时候,优雅的悬挂就更重要了。   

  

  本文以围棋计时任务为例,简要介绍围棋技术栈中优雅暂停的处理思想。   

  

  

02 适用人群      

  初学者-初级-中级-高级;这篇文章适合初学者及以上。   

  

  

03 代码级支持优雅中止是必要的      

     

  

  

优雅中止的含义      

  所谓“优雅挂起”是指应用程序收到特定的挂起信号(如INT、TERM)后,不再接受新的外部请求或创建新的内部任务,保持应用程序进程运行,直到旧的需求和任务完成后再终止退出。   

  

  

Kubernetes 中 Pod 的终止机制      

  作为一个高可靠的服务平台,k8s定义了终止Pod(Pod中运行的业务流程)的基本步骤:主动删除Pod时,系统会在强制终止Pod之前向每个容器中的主要流程发送term信号,然后在一段时间(默认为30秒)后向这些流程发送KILL信号。此外,k8s还提供了通过hook方法管理容器生命周期的能力,允许用户以定制的方式配置容器启动后或终止前执行的操作。   

  

  当镜像中封装的应用程序在k8s中运行时,如果应用程序实现了优雅的挂起机制,则可以充分利用上述k8s的能力,在应用程序升级(发布新版本)和管理Pod(主机在维护时将Pod漂移到另一台主机,或者在空闲时间动态收缩Pod的数量,以节省资源供其他使用)的过程中实现服务的零中断。   

  

  

优雅中止的 Go 代码示例      

  下面的代码定义了两个定时任务:每秒会触发一次mySecondJobs,每次持续1秒左右;MyMinuteJobs将每分钟触发一次,每次持续约2秒。具体来说,可以阅读下面的代码(可以直接复制下面的代码在自己的环境中运行):   

  

     

  

  

源码解读-优雅中止的处理思路      

  通过信号捕捉特定信号。通知;循环任务由for select实现,同时检测上一步要捕获的信号;如果定时器被触发,则执行相应的任务;如果找到指定的信号,跳出for循环,采取一些措施结束异步任务。

源码解读-值得关注的几个点      

  代码采用go mySecondJobs()和go myMinuteJobs()异步任务的方式;如果采用同步模式,则无法捕获信号,因为此时主线程正在处理业务逻辑,没有空闲的处理信号捕获逻辑。   

  

  源代码懒懒的采用了简单的等待方法来保证异步任务的正常结束,并不是通用的方法。在实际开发中,需要根据情况进行定制。   

  

  时间的使用。应注意股票。当select语句中的多个分支同时满足条件时,会随机选择一个执行,导致信息丢失(上一篇参考文献中提到)。不过本文中的代码不会触发这个问题,大家可以思考一下原因。   

  

  

03 小结      

     

  

  默认情况下,Go应用程序在收到TERM信号后直接退出主进程。如果此时有未完成的流程(比如收到外部请求后没有返回响应,或者内部异步任务没有完成),就会造成流程异常中断,影响服务质量。通过显式捕获代码中的$ TERM信号和其他信号,并感知操作系统对进程的处理,我们可以采取积极的措施来优雅地结束应用程序进程。   

  

  随着k8s的普及,考虑到其对进程生命周期的规范化管理,应用有必要支持优雅的代码级挂起(尤其是容器化的应用)作为开发规范,值得每一个开发者关注。   

  

  

参考      

  信号(Linux信号机制)_百度百科介绍LINUX中的信号(如SIGINT、SIGTERM等。)Pods-Kubernetes Kubernetes官网对Pods的介绍、对pod生命周期包括容器生命周期钩子的介绍-Kubernetes Kubernetes官方对容器生命周期钩子的介绍优雅地关闭了Kubernetes中的nginx-简书介绍了信号、k8s中pod的终止过程、nginx的优雅终止golang信号处理-快乐编程Golang的信号-郭博客园OS/signal 3360防止开发者捕捉sigkill和SIG stop问题# 963 golang/Go GitHub Go不允许捕捉SIGKILL和SIGSTOP使用select-case和time的注意事项。虽然本文中的例子不会触发,但是,当使用时间。Ticker,你应该注意这个小坑如何让一个服务器优雅的关机。问题# 1329Gin-Gonic/Gin GithubGo的Web框架。GIN对优雅悬浮的示例支持版权归作者所有。   

  

  原: https://jingwei.link/2019/03/31/golang-graceful-ending.html