让我们给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挺满足需求,它是一个不停机重启的服务器实现,实现流程为:

  1. 监听 SIGHUP 信号
  2. 收到信号后 fork 子进程(使用相同的启动命令),将服务监听的 socket 文件描述符传递给子进程
  3. 子进程启动成功后开始监听新的连接,并发送 SIGTERM 信号给父进程
  4. 父进程收到 SIGTERM 信号后停止接收新的连接,等待旧连接处理完成后终止
  5. 父进程终止,重启完成

关于 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程序不停机重启的更多相关文章

  1. endless 如何实现不停机重启 Go 程序?

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/584 前几篇文章讲解了如何实现一个高效的 HTTP 服务,这次我们来 ...

  2. linux 程序失败自动重启

    最近写了一个spark streaming 程序,但是程序跑着跑着就报错了,而且不会自动重启,以下脚本实现了程序失败自动重启 基本原理:查看程序日志文件是否有ERROR或Exception字样,有说明 ...

  3. C#程序注销、重启、关机和锁定电脑

    一:截图 二:源代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ...

  4. android程序崩溃后重启

    有时候由于测试不充分或者程序潜在的问题而导致程序异常崩溃,这个是令人无法接受的,在android中怎样捕获程序的异常崩溃,然后进行一些必要的处理或重新启动 应用这个问题困恼了我很久,今天终于解决了该问 ...

  5. 任务计划程序-Windows2008定时重启

    参考网站:https://www.cnblogs.com/yeyun/p/6209540.html Windows系统的任务计划程序,可以添加计划任务,设置任务开始时间及执行的间隔,实现应用的自动执行 ...

  6. 解决Android后台清理APP后,程序自动重启的问题

    最近解决了一个Android APP的bug,发现APP在被后台清理后,会自动重启.现象很奇怪,有的手机(HTC)后台清理后,程序会再次重启,而有的手机(小米)则不会.猜想可能是小米手机内部做了处理, ...

  7. java:如何让程序按要求自行重启?

    正文开始前的废话: 这里的程序即包括b/s的web application,也包括standalone的类c/s的java application.   为什么要自我重启?   场景1:分布式环境中, ...

  8. Qt之重启应用程序

    简介 今天分享的内容有些意思-如何重启一个应用程序.其实,有时候这是一个很重要的功能点,而且很人性化.易用性很好. 例如:切换用户.当某个用户登录成功之后,需要切换到其它账号,那么这时,你就知道它的重 ...

  9. 【Qt】Qt之重启应用程序【转】

    简介 今天分享的内容有些意思-如何重启一个应用程序.其实,有时候这是一个很重要的功能点,而且很人性化.易用性很好. 例如:切换用户.当某个用户登录成功之后,需要切换到其它账号,那么这时,你就知道它的重 ...

随机推荐

  1. ThreadLocal概念以及使用场景

    ThreadLocal概念以及使用场景 根据自身的知识深度,这里只限于自己使用和学习的知识点整理,原理的解释还需要再沉淀. 该文章从项目开发中举例,希望能帮助到各位,不了解ThreadLocal的朋友 ...

  2. C#特性知识图谱-二、事件

    C#特性知识图谱-二.事件 二.事件 在事件驱动的软件系统中,符合某种预设条件的情形出现是,一个事件就会被触发. 2.1 事件三要素 事件源:激发事件的对象 事件信息:事件本身说携带的信息 事件响应者 ...

  3. 使用寄存器点亮LED——2

    1. 项目:使用stm32寄存器点亮LED, 分别点亮红.绿.蓝3个灯. 2. 步骤 先新建个文件夹保存项目 再新建项目 将startup_stm32f10x_hd.s拷贝到该文件夹下 新建main. ...

  4. pip 安装软件报 Requirement already satisfied

    pip 安装的时候报错了,以为是豆瓣源有问题,换了还是一样,于是我们只需要加入一个参数 --target=路径    给它一个指定的位置就可以解决这个问题 安装位置不变,只是增加了一个参数在后面

  5. centos7 配置ftp服务器搭建(匿名访问,以及本地登录)

    大家好,今天来给大家分享一个基于centos 7的ftp服务器搭建 实现功能:匿名访问,本地登录 查看系统版本: [root@localhost ~]# cat /etc/redhat-release ...

  6. AtCoder Beginner Contest 224

    AtCoder Beginner Contest 224 A - Tires 思路分析: 判断最后一个字符即可. 代码如下: #include <bits/stdc++.h> using ...

  7. [no code][scrum meeting] Alpha 10

    项目 内容 会议时间 2020-04-16 会议主题 用户管理第一版交付 会议时长 15min 参会人员 PM+后端组成员 $( "#cnblogs_post_body" ).ca ...

  8. spring cloud中使用hystrix实现回退

    在微服务架构中,我们的服务被拆分成多个微服务,每个微服务完成自己的职责,微服务之间通过rpc或http进行调用.这个时候我们就要确保我们的服务高可用,但谁也说不准我们的服务能永远快速的提供服务.假如现 ...

  9. palindrome-partitioning leetcode C++

    Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...

  10. hdu 5172 GTY's gay friends(线段树最值)

    题意: GTY有n个朋友,站成一排,每个人有一个特征值ai. 有m个询问.每次询问给两个数L,R.问你[L,R](即aL...aR)是否是1..(R-L+1)的一个全排列. 是输出YES,否则输出NO ...