从nginx热更新聊一聊Golang中的伺服器热更新(上)
静态语言在伺服器编程时都会遇到这样的问题:如何保证已有的连接服务不中断同时又升级版本?
最近花了点时间看了下nginx热更新代码流程,想了下结合之前的经验一并总结下热更新
1. 热更新是什么?
简单翻译成人类可读的实例是如下这个样子:
举个例子,你现在在坐卡车,卡车开到了150KM/H
然后,有个轮胎,爆了
然后,司机说,你就直接换吧,我不停车。你小心点换嗯。就这个意思
2.网关中的热更新
服务程序热更新
这个问题在层7网关中尤其严重,网关中承载著大量的请求,包括HTTP/HTTPS短连接
、HTTP/HTTPS长连接
、甚至是websocket
这种超长连接(websocket通常连接时间会很长,十几分钟到几天不等)。这样的话我们势必不能讲服务程序停止再启动的冷更新
,服务进程热更新
是非常有必要的。
网关作为一个基础组件,需要保证高可用,是很难将其先停下来再更新的;
有人说可以使用负载均衡将需要更新的组件先隔离,再停机更新,但是如果是一个很小的集群没有负载均衡呢,又或者这样手动一台一台升级也著实麻烦,部分情况下就算隔离了也不过是不会有新的连接过来,旧的连接/请求依旧需要处理完成,否则就会造成部分服务不可用。
不过实际上线上操作是集群隔离加热更新一起操作
3.nginx热更新(Upgrading Executable on the Fly)
nginx [engine x]
是Igor Sysoev
编写的一个HTTP和反向代理伺服器
,另外它也可以作为邮件代理伺服器。 它已经在众多流量很大的俄罗斯网站上使用了很长时间,这些网站包括Yandex
、Mail.Ru
、VKontakte
,以及Rambler
。据Netcraft
统计,在2012年8月份,世界上最繁忙的网站中有11.48%
使用Nginx
作为其伺服器或者代理伺服器。
NginX采用
Master/Worker
的多进程模型,Master
进程负责整个NginX
进程的管理。Nginx
的模块化
、热更新
、Http处理流程
、日志
等机制都非常经典。这里将会简要介绍一下热更新的机制
3.1 nginx热升级流程
步骤1、升级nginx二进位文件
,需要先将新的nginx可执行文件
替换原有旧的nginx文件
,然后给nginx master进程
发送USR2信号
,告知其开始升级可执行文件;nginx master进程
会将老的pid
文件增加.oldbin后缀
,然后拉起新的master
和worker进程
,并写入新的master进程的pid
。
UID PID PPID C STIME TTY TIME CMD
root 4584 1 0 Oct17 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
root 12936 4584 0 Oct26 ? 00:03:24 nginx: worker process
root 12937 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 12938 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 23692 4584 0 21:28 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
root 23693 23692 3 21:28 ? 00:00:00 nginx: worker process
root 23694 23692 3 21:28 ? 00:00:00 nginx: worker process
root 23695 23692 3 21:28 ? 00:00:00 nginx: worker process
步骤2、在此之后,所有工作进程(包括旧进程和新进程)
将会继续接受请求。这时候,需要发送WINCH
信号给nginx master进程
,master进程
将会向worker进程
发送消息,告知其需要进行graceful shutdown
,worker进程
会在连接处理完之后进行退出。
UID PID PPID C STIME TTY TIME CMD
root 4584 1 0 Oct17 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
root 12936 4584 0 Oct26 ? 00:03:24 nginx: worker process
root 12937 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 12938 4584 0 Oct26 ? 00:00:04 nginx: worker process
root 23692 4584 0 21:28 ? 00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx
#若旧的worker进程还需要处理连接,则worker进程不会立即退出,需要待消息处理完后再退出
步骤3、经过一段时间之后,将会只会有新的worker进程处理新的连接。
注意,
旧master进程
并不会关闭它的listen socket
;因为如果出问题后,需要回滚,master进程需要法重新启动它的worker进程。
步骤4、如果升级成功,则可以向旧master进程
发送QUIT信号,停止老的master进程
;如果新的master进程
(意外)退出,那么旧master进程
将会去掉自己的pid文件的.oldbin后缀。
3.2 nginx热更新相关信号
master进程相关信号
USR2 升级可执行文件
WINCH 优雅停止worker进程
QUIT 优雅停止master进程
worker进程相关信号
TERM, INT 快速退出进程
QUIT 优雅停止进程