beego 优雅重启
前言
最近在写 go 的项目, http 用的 beego 框架. 因为 go 不想 php, 每次代码改动都需要重启服务, 所以代码发上线之后, 如何重启服务就成了一个问题. 如果强行重启的话, 不光在重启期间的所有访问都被拒绝了, 而且在杀掉进程的时候处理中的请求也挂了. 对于一个向用户正常提供服务的服务器来说, 这种情况自然是无法容忍的.
在我的设想中, 服务的重启应该是启动进程处理新的请求, 而老进程则等待将现有请求处理完再退出, 这样就可以无缝重启了.
想法是好的, 结果网上搜了半天, 都是针对 http 系统模块的, 没有找到 beego 的优雅重启. 但是我还很纳闷, 这么流行的框架, 竟然没有人写过? (当然, 后面完美的证明了我的愚蠢)
尝试
在我搜了半天没有找到的时候, 机智的我自然就要动手自己搞了.在我的设想中, 大概分为以下三步:
- 接收服务重启的命令
- 老进程停止接收请求并在现有请求处理完后退出
- 启动新进程处理新的请求
想法是好的, 接下来就是如何实现了, 一步一步来.
第一步很简单, 说白了就是如何向进程发送消息, 我尝试了修改本地文件, 也想过用消息队列, 不过最终还是选择了大多数人的选择, kill
命令发送信号量.
准备开始第二步了, 这个时候就坑了. 首先, beego
的运行只有一条命令beego.run()
. 很显然, 它将http
封装了起来, 所以要想在停止端口监听的同时, 进程继续处理现有请求, 只有两条路走. 一是beego
有暴露的方法支持停止端口监听的操作. 二就是重写beego
源码. 而重写源码就意味着之后就不能跟着版本进行更新了, 所以是下下策.
不管怎么说吧, 先对beego
的启动机制有个了解是必要的. 就从run
方法进去. 而就在我进入方法走了没两步, 看到了这样的代码:
看注释. 启动优雅模式. 这这这这, 这不就是我要的么?????? 这我整半天整了个毛啊, 人家一开始就支持. 尝试一下, 将值置为 true 试一下:
beego.BConfig.Listen.Graceful = true
那么问题来了, beego
是如何接收信号的呢? 从下面调用的ListenAndServe
方法走进去. 找到启动信号监听的地方, 然后看一下监听的是哪个信号就可以了. 结果, 往里走了两个方法就找到了:
显然, 通过HUP
信号会启动子进程来实现优雅重启, 而INT
信号会令进程停止. 然后我验证了一下.
- 在
beego
运行前修改其配置:beego.BConfig.Listen.Graceful = true
- 通过
kill -HUP pid
命令重启.
简单试了一下, 确实实现了优雅重启. 原进程会在请求处理完之后停止.
另外, 也可以在app.conf
中通过配置来启动优雅重启:
Graceful=false
总结
最后, 我到google
重新搜了一下: beego graceful
. 结果发下其赫然躺在搜索结果的第一条. 我???
所以, 之后要尽量使用英文关键词搜索, 中文搜索有时定位不到准确的结果, 反而浪费了大量时间. 就比如这次, 如果最开始搜到了这条, 可能十几分钟就搞出来了. 偏偏最后我翻源码翻了几个小时, 得出的结论和那十几分钟的还是一样的. 好气呀.
谨以此记录我这被自己坑的一次.