Go项目实现优雅关机与平滑重启
Demo快速上手
优雅关机
package mainimport ("context""github.com/gin-gonic/gin""log""net/http""os""os/signal""syscall""time"
)// 实现优雅关机和平滑重启
func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {// 这个10秒的延时。是为了演示操作方便,实际上线一定注释掉time.Sleep(time.Second * 10)c.String(http.StatusOK, "hello xiaosheng")})srv := &http.Server{Addr: ":8080",Handler: router,}// 必须开启一个go routine 因为如果不开起,下面会一直listen and serve,进入死循环// err != http.ErrServerClosed这个很重要go func() {// 开启一个goroutine启动服务if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {log.Fatalf("listen : %s\n", err)}}()// 等待中断信号来优雅关掉服务器, 为关闭服务器做一个5秒的延时quit := make(chan os.Signal, 1)// kill 默认会发送syscall.SIGTREN信号// kill -2发送syscall.SIGINT信号,我们常用的ctrl+c就是触发系统SIGINT信号// kill -9发送syscall.SIGKILL信号,但是不能被捕获,所以不需要添加他// signal.Notify把收到的syscall.SIGINT或syscall.SIGTREN信号传给quitsignal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此处不会阻塞<-quit // 阻塞在此,当收到上述两种信号的时候才会往下执行log.Println("ShutDown Server ...")// 创建一个5秒超时的contextctx, cancel := context.WithTimeout(context.Background(), time.Second*5)defer cancel()// 5秒内优雅关闭服务, (将未处理完的请求处理完再关闭服务), 超过5秒就退出if err := srv.Shutdown(ctx); err != nil {log.Fatal("shut down:", err)}log.Println("Server exiting...")
}
平滑重启
import ("log""net/http""time""github.com/fvbock/endless""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {// 这个5秒的延时。是为了演示操作方便,实际上线一定注释掉time.Sleep(5 * time.Second)c.String(http.StatusOK, "hello gin!")})// 默认endless服务器会监听下列信号:// syscall.SIGHUP,syscall.SIGUSR1,syscall.SIGUSR2,syscall.SIGINT,syscall.SIGTERM和syscall.SIGTSTP// 接收到 SIGHUP 信号将触发`fork/restart` 实现优雅重启(kill -1 pid会发送SIGHUP信号)// 接收到 syscall.SIGINT或syscall.SIGTERM 信号将触发优雅关机// 接收到 SIGUSR2 信号将触发HammerTime// SIGUSR1 和 SIGTSTP 被用来触发一些用户自定义的hook函数if err := endless.ListenAndServe(":8080", router); err!=nil{log.Fatalf("listen: %s\n", err)}log.Println("Server exiting...")
Detail
优雅关机
服务端关机命令发出后不立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,这样是一种对客户端友好的关机方式。
执行Ctrl+C时,会强制结束进程,这样导致正在访问的请求出现问题。
Go 1.8
版本之后, http.Server
内置的 Shutdown()
方法就支持优雅关机
流程
8080端口开启了一个web服务,并且只注册了一条路由,“/”, 但客户端访问127.0.0.1:8080/
时,过10秒才会响应,如果这时我们按下ctrl+c,给程序发送syscall.SIGINT信号,他会等待10秒将当前请求处理完,他才会消亡,当然也取决于创建的5秒的context超时时间。
平滑重启
可以使用fvbock/endless
来替换默认的 ListenAndServe
启动服务来实现
import ("log""net/http""time""github.com/fvbock/endless""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {// 这个5秒的延时。是为了演示操作方便,实际上线一定注释掉time.Sleep(5 * time.Second)c.String(http.StatusOK, "hello xiaosheng !")})// 默认endless服务器会监听下列信号:// syscall.SIGHUP,syscall.SIGUSR1,syscall.SIGUSR2,syscall.SIGINT,syscall.SIGTERM和syscall.SIGTSTP// 接收到 SIGHUP 信号将触发`fork/restart` 实现优雅重启(kill -1 pid会发送SIGHUP信号)// 接收到 syscall.SIGINT或syscall.SIGTERM 信号将触发优雅关机// 接收到 SIGUSR2 信号将触发HammerTime// SIGUSR1 和 SIGTSTP 被用来触发一些用户自定义的hook函数if err := endless.ListenAndServe(":8080", router); err!=nil{log.Fatalf("listen: %s\n", err)}log.Println("Server exiting...")
流程
- 在终端执行
go build -o graceful_restart
编译,并执行./graceful_restart
,终端输出当前pid(假设为44444) - 将代码中处理请求函数返回的
hello xiaosheng!
修改为hello world!
,再次编译go build -o graceful_restart
- 打开浏览器访问
127.0.0.1:8080/
,此时客户端浏览器等待服务端返回响应。 - 在终端执行
kill -1 44444
命令给程序发送syscall.SIGHUP
重启信号 - 等第3步客户端浏览器收到响应信息
hello xiaosheng!
后,再次访问127.0.0.1:8080/
会收到hello world!
的响应。
这样做在不影响当前未处理完请求的同时完成了程序代码的替换,实现了平滑重启。但实际上用的不多,因为实际都是多台服务器,或者说有类似supervisor
的软件管理进程时就不适用这种方式,因为他进程pid变了,他自己重启和supervisor
的软件管理进程给他重启就冲突了。
Go项目实现优雅关机与平滑重启相关推荐
- Go实现优雅关机与平滑重启
前言 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式.而执行Ctrl+C关闭服务端时,会强制结束进程导致正在访问的请求出 ...
- Golang服务平滑重启
与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可.平滑重启意味着server升级的时候可以不用停止业务. 我们先来看 ...
- supervisor 重启_Golang HTTP服务平滑重启及升级
Golang HTTP服务在上线时,需要重新编译可执行文件,关闭正在运行的进程,然后再启动新的运行进程.对于访问频率比较高的面向终端用户的产品,关闭.重启的过程中会出现无法访问(nginx表现为502 ...
- 电脑关闭计算机怎么重启计算机,教您电脑关机后总是重启怎么办
电脑关机后自动重启的问题,一直困扰一些朋友,通常就是关闭系统后,电脑又自己开机启动了,我们不得不拔掉电源或强制关机,要解决电脑无法关机变重启的问题就要找到原因然后解决,下面,小编讲处理电脑关机后总是重 ...
- java jar包 平滑重启,nginx 平滑重启的实现方法
一.背景 在服务器开发过程中,难免需要重启服务加载新的代码或配置,如果能够保证server重启的过程中服务不间断,那重启对于业务的影响可以降为0.最近调研了一下nginx平滑重启,觉得很有意思,记录下 ...
- K8s上的Go服务怎么扩容、发版更新、回滚、平滑重启?教你用Deployment全搞定!
经过前面不少文章的铺垫,终于可以写这个大家都感兴趣的话题了,在前面两篇文章,我们讲了Kubernetes里的 Pod和 副本集ReplicaSet (RS) 这两个API对象.知道了Pod是Kuber ...
- 关机状态下启动微型计算机叫什么,教你电脑关机后自动重启是什么原因
很多朋友都想要知道电脑关机后自动重启有什么原因,其实电脑关机后自动重启是非常简单,如果大家想要了解的话,小编当然会告诉大家电脑关机后自动重启的原因!下面就给大家带来电脑关机后自动重启原因的介绍吧. 小 ...
- xp计算机重启记录,XP电脑关机后自动重启的解决方法
有些xp系统用户反映在按了关机键后,电脑却莫名其妙地又自动重启了,这是怎么回事?应该怎么办?下面小编为大家介绍一下解决方法. 一.系统失败导致自动重启 1.在桌面上"我的电脑"鼠标 ...
- php:php-fpm平滑重启为什么无效
一.问题 今天修改了fpm一些配置,需要上线重启fpm,但是发现一瞬间出现很多502的错误请求,查看日志发现以下错误 fpm:重启日志 nginx:错误日志 2023/04/23 15:19:00 [ ...
最新文章
- Java 如何设计 API 接口,实现统一格式返回?
- Zend SDK学习-1
- Android性能优化
- 计算机网络按信号频带占用方式分为,《计算机网络及组网技术》第2阶段测试题....
- LIS(基于贪心的O(NlogN)解法)
- 使用泛型实现单例提供者(原创翻译)
- [基础]PeopleSoft中的作业和调度作业集合定义
- Redis5.0重量级特性Stream尝鲜
- 孙鑫-MFC笔记三--绘图
- jquery和prototype冲突解决
- Neo4j下载安装以及Neo4j浏览器详细说明
- 什么是DC-DC转换器?DC-DC转换器是如何命名的?
- Oauth2.0 资源服务器搭建
- N款在线图片处理工具,让你的效率翻倍
- 推荐2个适合程序员使用的显示器
- 编译原理:语法制导翻译
- 如何找回存储在DBeaver连接中的数据库密码
- 论混合软件架构的设计
- 王自如评价鸿蒙OS,王自如发表致歉声明 测评将加利益相关说明
- python学习笔记(推荐有其他语言编程经验想学python的人看)
热门文章
- Java开发的模拟双色球抽奖程序 功能非常齐全 完整源码
- 应用Abaqus有限元软件中的cohesive单元模拟压头侵入地层随机断裂过程
- MATLAB 遭禁,CAD 也危险,国产工业软件如何突围?
- 1253:抓住那头牛(数轴上的问题)
- nodejs+vue+elementui二手车评估信息网站系统java python
- 【个人笔记】OpenCV4 C++ 快速入门 28课
- 【Linux】CPU频率控制|Conflicting CPU frequency values detected
- 【LTE】为什么使用SNR来表征信道质量,而并不用RSRQ?这两者的区别是什么?
- Kotlin小知识之高阶函数
- 玩转树莓派之环境搭建—安装TFT屏