Golang 平滑关闭/重启与热编译技术
1 平滑关闭
本文所讨论的平滑关闭是指,HTTP服务、RPC服务、Socket长服务等各种网络服务的平滑关闭。
1.1 平滑关闭的步骤
1.2 关键点:跟踪所有连接的状态
跟踪所有连接的状态是做到平滑关闭的关键。
一个连接,通常有如下几种状态:
- New 新建的连接
- Active 活动中的连接
- Idle 未断开的空闲连接
- Hijacked 被其他网络服务劫持的连接
- Closed 已关闭的连接
通常的做法是,使用一个map字典记录listener接收到的所有连接conn及其状态,并在conn发生状态改变时,修改其状态。
1.3 实现平滑关闭操作
首先,将关闭listener、关闭空闲conn、等待新建及活动连接的关闭、处理自定义收尾工作这几项功能封装为一个Shutdown函数。形式或许为:
func Shutdown(context.Context) error
其中,Context可以定义超时条件。
其次,我们可以通过给进程发生软中断信号(如Linux的kill命令,windows的Ctrl+C)来触发调用Shutdown函数,执行平滑关闭操作。
或者也可以通过API接口,在新的协程中调用该函数,可以达到同样效果。
2 平滑重启
平滑重启,又叫做平滑升级、优雅重启。实际上它包含两部分内容:
- 平滑关闭老进程
- 无停服切换至新进程
平滑关闭在上面第1章节已经讲述,因此该章节只讨论无停服切换新进程的问题。
严格意义的无停服切换新进程只在Linux阵营可以实现。Windows是不支持的,只能尽力缩短停服时间。
2.1 平滑重启步骤
Linux下的平滑重启步骤:
- 如需升级服务则用新的可执行文件替换老的可执行文件,如只需平滑重启则跳过这一步
- 通过信号或API调用平滑重启函数,完成操作:
StartProcess(name string,argv []string,attr *ProcAttr) (*Process,error)
2.2 调用平滑重启函数
在Linux下,我们通常使用kill -USR2 [pid]
来发送信号,调用平滑重启函数。
3 热编译
热编译是使用第三方工具来自动编译、运行服务的一种方式。一定程度上类似于平滑重启,比如windows下只能使用该方式模拟平滑重启,达到接近无停服的效果。
3.1 热编译的步骤
使用第三方工具的执行热编译的步骤: