go程序不停机重启
让我们给http服务写一个版本更新接口,让它自动更新版本并重启服务吧。
初步例子
注:为了精简,文中代码都去除了err处理
main.go
var Version = "1.0"
/* 打印版本 */
func version(w http.ResponseWriter, r *http.Request) {
msg := fmt.Sprintf("version %v\n", Version)
w.Write([]byte(msg))
}
/* 版本升级 */
func upgrade(w http.ResponseWriter, r *http.Request) {
// 1. 把新版本文件放置到服务主目录(简化)
os.Remove("test_restart")
os.Rename("new_test_restart", "test_restart")
// 2. go的可执行文件加权限(省略)
// 3. 重启服务
cmd := exec.Command("/bin/bash", "-c", "./restart.sh")
cmd.Output()
w.Write([]byte("restart ok\n"))
}
func main() {
// 记录pid
f,_ := os.Create("s.pid")
pid := os.Getpid()
f.WriteString(fmt.Sprintf("%v", pid))
fmt.Printf("System running:%v\n", pid)
// 监听连接
mux := http.NewServeMux()
mux.HandleFunc("/version", version)
mux.HandleFunc("/upgrade", upgrade)
http.ListenAndServe("127.0.0.1:9527", mux)
}
restart.sh(重启脚本)
kill -9 $(cat s.pid)
nohup ./test_restart > nohup.log 2>&1 &
测试
1. 编译后开始运行

2. 请求一下版本信息接口

3. 将代码中Version改为“1.1”, 生成一个新文件“new_test_restart”
4. 请求版本更新接口


发现问题
重启脚本是stop后start的,stop时直接杀死了进程,程序直接中断了当前所有的连接,此时接口函数还未return,导致调用方接收不到响应。
使用Endless
看来得不中断已有连接的情况下进行重启才行,不能简单的stop后start,得平滑重启。大致就是让父进程启动一个子进程去监听新的连接,自己不再监听新的连接,而是在处理完已有连接后终止,之后子进程独挑大梁。
随后发现github上的endless挺满足需求,它是一个不停机重启的服务器实现,实现流程为:
- 监听 SIGHUP 信号
- 收到信号后 fork 子进程(使用相同的启动命令),将服务监听的 socket 文件描述符传递给子进程
- 子进程启动成功后开始监听新的连接,并发送 SIGTERM 信号给父进程
- 父进程收到 SIGTERM 信号后停止接收新的连接,等待旧连接处理完成后终止
- 父进程终止,重启完成
关于 SIGHUP 信号,我们可以用“kill -1”命令发送给endless。
使用endless改动很小,在main函数中只需要把 http.ListenAndServe 修改为 endless.ListenAndServe即可:
main.go
func main() {
// 记录pid(省略)
// 监听连接
mux := http.NewServeMux()
mux.HandleFunc("/version", version)
mux.HandleFunc("/upgrade", upgrade)
// http.ListenAndServe("127.0.0.1:9527", mux)
endless.ListenAndServe("127.0.0.1:9527", mux)
}
restart.sh
kill -1 $(cat s.pid)
再测试
1. 编译后开始运行(带时间前缀的是endless打印的日志)

2. 请求一下版本信息接口

3. 将代码中Version改为“1.1”, 生成一个新文件“new_test_restart”
4. 请求版本更新接口


请求没有被中断,成功接收了响应。
endless的日志比较清晰,77625的父进程接收 SIGHUP 后,fork了子进程77625,接收到子进程传递的 SIGHUP 后,等待已有连接处理完成后终止,完全符合上述介绍的流程。
5. 验证版本

至此,不停机版本更新成功 ٩(◕‿◕。)۶
go程序不停机重启的更多相关文章
- endless 如何实现不停机重启 Go 程序?
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/584 前几篇文章讲解了如何实现一个高效的 HTTP 服务,这次我们来 ...
- linux 程序失败自动重启
最近写了一个spark streaming 程序,但是程序跑着跑着就报错了,而且不会自动重启,以下脚本实现了程序失败自动重启 基本原理:查看程序日志文件是否有ERROR或Exception字样,有说明 ...
- C#程序注销、重启、关机和锁定电脑
一:截图 二:源代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ...
- android程序崩溃后重启
有时候由于测试不充分或者程序潜在的问题而导致程序异常崩溃,这个是令人无法接受的,在android中怎样捕获程序的异常崩溃,然后进行一些必要的处理或重新启动 应用这个问题困恼了我很久,今天终于解决了该问 ...
- 任务计划程序-Windows2008定时重启
参考网站:https://www.cnblogs.com/yeyun/p/6209540.html Windows系统的任务计划程序,可以添加计划任务,设置任务开始时间及执行的间隔,实现应用的自动执行 ...
- 解决Android后台清理APP后,程序自动重启的问题
最近解决了一个Android APP的bug,发现APP在被后台清理后,会自动重启.现象很奇怪,有的手机(HTC)后台清理后,程序会再次重启,而有的手机(小米)则不会.猜想可能是小米手机内部做了处理, ...
- java:如何让程序按要求自行重启?
正文开始前的废话: 这里的程序即包括b/s的web application,也包括standalone的类c/s的java application. 为什么要自我重启? 场景1:分布式环境中, ...
- Qt之重启应用程序
简介 今天分享的内容有些意思-如何重启一个应用程序.其实,有时候这是一个很重要的功能点,而且很人性化.易用性很好. 例如:切换用户.当某个用户登录成功之后,需要切换到其它账号,那么这时,你就知道它的重 ...
- 【Qt】Qt之重启应用程序【转】
简介 今天分享的内容有些意思-如何重启一个应用程序.其实,有时候这是一个很重要的功能点,而且很人性化.易用性很好. 例如:切换用户.当某个用户登录成功之后,需要切换到其它账号,那么这时,你就知道它的重 ...
随机推荐
- 华为Awareness kit,您旅途路上的超智能管家
前言 前段时间看了一部纪录片<中国游客在巴黎>,讲述了外国人眼中"中国式旅游":热衷景点打卡,沉迷拍照留念,无暇仔细欣赏:留足时间,买买买,不能枉此行.网友总结中国式旅 ...
- Server Tools(服务器工具)
服务器工具 1.发布 # Process: MXD 转 Web 地图 arcpy.MXDToWebMap_server("", "", "" ...
- 洛谷4234最小差值生成树 (LCT维护生成树)
这也是一道LCT维护生成树的题. 那么我们还是按照套路,先对边进行排序,然后顺次加入. 不过和别的题有所不同的是: 在本题中,我们需要保证LCT中正好有\(n-1\)条边的时候,才能更新\(ans\) ...
- 【日志技术专题】「logback入门到精通」彻彻底底带你学会logback框架的使用和原理(入门介绍篇)
技术介绍 什么是 logback? Logback为取代 log4j 而生.Logback 由 log4j 的创立者 Ceki Gülcü设计.以十多年设计工业级记录系统的经验为基础,所创建的logb ...
- SpringBoot配置文件application
配置文件 SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的,有两种文件格式: application.properties 语法结构 :key=value application. ...
- VS2019中安装2017,2015
VS2019中安装2017,2015
- Java:死锁编码及定位分析
Java:死锁编码及定位分析 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 概念 死锁是指两个或多个以上的进程在执行过程中,因争夺资源而造成一种互相等待的现象, ...
- 并发编程从零开始(八)-ConcurrentHashMap
并发编程从零开始(八)-ConcurrentHashMap 5.5 ConcurrentHashMap HashMap通常的实现方式是"数组+链表",这种方式被称为"拉链 ...
- Noip模拟76 2021.10.14
T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...
- 2021.9.14考试总结[NOIP模拟53]
T1 ZYB和售货机 容易发现把每个物品都买成$1$是没有影响的. 然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以 ...