Go程序如何来做热升级

Wesley13
• 阅读 662

热升级是什么?

热升级是什么呢?了解nginx的同学都知道,nginx是支持热升级的,可以用老进程服务先前链接的链接,使用新进程服务新的链接,即在不停止服务的情况下完成系统的升级与运行参数修改。那么热升级和热编译是不同的概念,热编译是通过监控文件的变化重新编译,然后重启进程,例如bee start就是这样的工具

热升级有必要吗?

很多人认为HTTP的应用有必要支持热升级吗?那么我可以很负责的说非常有必要,不中断服务始终是我们所追求的目标,虽然很多人说可能服务器会坏掉等等,这个是属于高可用的设计范畴,不要搞混了,这个是可预知的问题,所以我们需要避免这样的升级带来的用户不可用。你还在为以前升级搞到凌晨升级而烦恼嘛?那么现在就赶紧拥抱热升级吧。

beego如何支持热升级

热升级的原理基本上就是:主进程fork一个进程,然后子进程exec相应的程序。那么这个过程中发生了什么呢?我们知道进程fork之后会把主进程的所有句柄、数据和堆栈、但是里面所有的句柄存在一个叫做CloseOnExec,也就是执行exec的时候,copy的所有的句柄都被关闭了,除非特别申明,而我们期望的是子进程能够复用主进程的net.Listener的句柄。一个进程一旦调用exec类函数,它本身就"死亡"了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。

那么我们要做的第一步就是让子进程继承主进程的这个句柄,我们可以通过os.StartProcess的参数来附加Files,把需要继承的句柄写在里面。

第二步就是我们希望子进程能够从这个句柄启动监听,还好Go里面支持net.FileListener,直接从句柄来监听,但是我们需要子进程知道这个FD,所以在启动子进程的时候我们设置了一个环境变量设置这个FD。

第三步就是我们期望老的链接继续服务完,而新的链接采用新的进程,这里面有两个细节,第一就是老的链接继续服务,那么我们怎么有老链接存在?所以我们必须每次接收一个链接记录一下,这样我们就知道还存在没有服务完的链接,第二就是怎么让老进程停止接收数据,让新进程接收数据呢?大家都监听在同一个端口,理论上是随机来接收的,所以这里我们只要关闭老的链接的接收就行,这样就会使得在l.Accept的时候报错。

上面是我们需要解决的三个方面的问题,具体的实现大家可以看我实现的代码逻辑。

如何演示热升级

  1. 编写代码,在beego应用的控制器中Get方法实现大概如下:

    func (this *MainController) Get() {
        a, _ := this.GetInt("sleep")
        time.Sleep(time.Duration(a) * time.Second)
        this.Ctx.WriteString("ospid:" + strconv.Itoa(os.Getpid()))
    }
    
  2. 打开两个终端

    一个终端输入:ps -ef|grep 应用名

    一个终端输入请求:curl "http://127.0.0.1:8080/?sleep=20"

  3. 热升级

    kill -HUP 进程ID

  4. 打开一个终端输入请求:curl "http://127.0.0.1:8080/?sleep=0"

我们可以看到这样的结果,第一个请求等待20s,但是处理他的是老的进程,热升级之后,第一个请求还在执行,最后会输出老的进程ID,而第二次请求,输出的是新的进程ID

点赞
收藏
评论区
推荐文章
菜鸟阿都 菜鸟阿都
2年前
SpringBoot项目热部署
前言   此篇文章主要介绍两种springboot项目热部署的方式,方式一是通过引入devtool组件实现热部署,方式二是通过idea下载jrebel插件实现热部署,jrebel免费试用30天,但通过激活网站可获得jrebel激活序列码,阿都对两种方式都进行了测试,全部有效。一、devtool组件热部署实现原理:自动重启项目1.添加devtools依赖
Karen110 Karen110
2年前
【前端自动化】如何使用Node.js实现热重载页面
前言前不久我结合browsersyncgulpgulpnodemon实现了一款生产环境热更新(我之前理解有点偏差,应该定义为热更新,不是热重载)的项目脚手架,那么,今天我们将使用Node.js实现一个热重载页面。那么,我今天就总结一下吧,以防止大家也跟我一样。热重载所谓热重载就是页面每次改动,不需要手动去刷新,可自动刷新。热更新浏览器的无刷新更新,允许在
Easter79 Easter79
2年前
springboot热部署实战
每次代码改动后都需要重新手动Run项目,心累,在网上找了下,发现SpringBoot提供了热部署的方案,改动代码后自动编译打包,现在将热部署的配置方法记下来:第一步:在pom.xml中添加依赖,导入springbootdevtools<dependency<groupIdorg.springframework
Wesley13 Wesley13
2年前
unity热更(一)
Agenda•  什么是热更新•  为何要热更新•  如何在iOS 上对Unity 应用进行热更新•  支持UnityiOS 热更新的各种Lua 插件的对比什么是热更新• 广义定义• 无需关闭服务器,不停机状态下修复漏洞,更新资源等,重点是更新逻辑代码。• 狭义定义(iOS热更新)• 无需将代码重新打包提交至Ap
Wesley13 Wesley13
2年前
Unity3D热更新之LuaFramework篇[10]
背景19年年初的时候,进到一家新单位,公司正准备将现有的游戏做成支持热更的版本。于是寻找热更方案的任务就落在了我头上。经过搜索了解,能做Unity热更的方案是有好几种,但是要么不够成熟,要么不支持iOS平台,相对来说,还是用Lua来实现比较靠谱。而Lua的热更方案也有好几种:xLua、toLua和sLua。其
Stella981 Stella981
2年前
SpringBoot热部署与启动速度优化
SpringBoot热部署  默认情况下SpringBoot是不支持热部署的,所以当每次修改代码的时候,都需要重新启动服务器,这个是非常浪费时间的,所以可以在pom.xml文件里面导入以下依赖1<dependency2<groupIdorg.springframework.boot</groupId
Wesley13 Wesley13
2年前
Go配置文件热加载
在日常项目的开发中,我们经常会使用配置文件来保存项目的基本元数据,配置文件的类型有很多,如:JSON、xml、yaml、甚至可能是个纯文本格式的文件。不管是什么类型的配置数据,在某些场景下,我们可会有热更新当前配置文件内容的需求,比如:使用Go运行的一个常驻进程,运行了一个WebServer服务进程。此时,如果配置文件发生变化,我们
Easter79 Easter79
2年前
SpringBoot热部署与启动速度优化
SpringBoot热部署  默认情况下SpringBoot是不支持热部署的,所以当每次修改代码的时候,都需要重新启动服务器,这个是非常浪费时间的,所以可以在pom.xml文件里面导入以下依赖1<dependency2<groupIdorg.springframework.boot</groupId
Stella981 Stella981
2年前
Nginx
!(https://imagestatic.segmentfault.com/255/117/25511790966008dc5b00fd8)Nginx进程模型分析在介绍Nginx的进程模型之前我们先来给大家解释下一些常见的名词,这能辅助我们更好的了解Nginx的进程模型。作为Web服务器,设计的初衷就是为了能够处理更多的客户端的请
京东云开发者 京东云开发者
10个月前
Spring Loaded代码热更新实践和原理分析 | 京东云技术团队
本文将深入探讨如何利用SpringLoaded热更新技术提高开发效率,减少编译和重启时间。分析SpringLoaded的热更新原理,以及实际应用过程中所需的操作和注意事项。