天,产品那边发来需求,说有个 APP 的 IOS 版本下载包需要新增 https 协议,在景安购买了免费的 SSL 证书。当我往 nginx 上新增 ssl 时,发现服务器上的 nginx 居然没编译 SSL 模块!
看了下旧版本 nginx 的 configure 选项:
1 2 3 4 | linux–gz215:# /usr/local/sbin/nginx -V nginx version: nginx/1.0.11 built by gcc 4.1.2 20070115 (prerelease) (SUSE Linux) configure arguments: —prefix=/usr/local/nginx |
可能是出于最小化安装的考虑,就只有一个 prefix 参数,而版本也挺低的,干脆就升级一下好了!由于服务器处于在线服务状态,为了避免升级带来的不良影响,我决定给 nginx 来个平滑升级,结果发现还真是如丝般顺滑。。。
下面记录一下平滑升级和新增模块的过程。
一、半自动平滑升级
所谓半自动,其实就是在最后迁移的时候使用源码自带的升级命令:make upgrade 来自动完成。
①、按需编译新版本的 nginx
根据需求,常规编译新版本 nginx,不过只要执行到 make 就打住,不要 make install!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #下载1.5.7版本,并解压 cd /usr/local/src wget http://nginx.org/download/nginx–1.6.0.tar.gz tar zxvf nginx–1.6.0.tar.gz cd nginx–1.6.0 #根据实际需要新增的模块,先准备所需文件(其实只需要解压即可,全部安装,后面编译就可以不指定路径了): #1. 安装pcre: wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre–8.34.tar.gz tar –zxvf pcre–8.34.tar.gz cd pcre–8.34 ./configure && make && make install #2. 安装zlib: cd /usr/local/src wget http://zlib.net/zlib–1.2.8.tar.gz tar –zxvf zlib–1.2.8.tar.gz cd zlib–1.2.8 ./configure && make && make install #3. 安装openssl: cd /usr/local/src wget http://www.openssl.org/source/openssl–1.0.1c.tar.gz tar –zxvf openssl–1.0.1c.tar.gz cd openssl–1.0.1c ./configure && make && make install #加上所需参数开始编译: ./configure —user=www —group=www —prefix=/usr/local/nginx —with–http_ssl_module —with–openssl=/usr/local/src/openssl–1.0.1c #对应openssl源码解压后的路径,下同(pcre,zlib) —with–http_stub_status_module —with–pcre —with–pcre=/usr/local/src/pcre–8.21 —with–zlib=/usr/local/src/zlib–1.2.8 #执行make编译,但是不要执行make install make |
②、重命名 nginx 旧版本二进制文件,即 sbin 目录下的 nginx(期间 nginx 并不会停止服务!):
1 | linux–gz215:/usr/local/src/nginx–1.6.0 # mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old |
③、然后拷贝一份新编译的二进制文件:
1 | linux–gz215:/usr/local/src/nginx–1.6.0 # cp objs/nginx /usr/local/nginx/sbin/ |
④、在源码目录执行 make upgrade 开始升级:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | linux–gz215:/usr/local/src/nginx–1.6.0 # make upgrade #下面是make upgrade命令的打印信息: /usr/local/nginx/sbin/nginx –t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful kill –USR2 `cat /usr/local/nginx/logs/nginx.pid` sleep 1 test –f /usr/local/nginx/logs/nginx.pid.oldbin kill –QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin` #最后确认一下nginx进程,可以发现有2个主进程,并且有正在关闭的进程(shutting down): linux–gz215:/usr/local/src/nginx–1.6.0 # ps aux | grep nginx root 969 0.0 0.3 8260 1844 ? Ss Dec09 0:01 nginx: master process /usr/local/nginx/sbin/nginx –c /usr/local/nginx/conf/nginx.conf www 4196 0.1 2.5 19112 12872 ? S 14:52 0:00 nginx: worker process is shutting down www 4260 0.1 2.5 19112 12872 ? S 14:52 0:00 nginx: worker process is shutting down www 4257 0.1 2.5 19112 12872 ? S 14:52 0:00 nginx: worker process is shutting down root 4663 0.0 0.3 5488 1900 ? S 14:58 0:00 nginx: master process /usr/local/nginx/sbin/nginx –c /usr/local/nginx/conf/nginx.conf #过一段时间后,再次确认nginx进程,可以发现老进程已自动退出了(存在一段时间是因为旧进程还有未结束的服务) root 969 0.0 0.3 8260 1844 ? Ss Dec09 0:01 nginx: master process /usr/local/nginx/sbin/nginx –c /usr/local/nginx/conf/nginx.conf www 4665 0.1 2.4 16508 12444 ? S 14:58 0:01 nginx: worker process |
完成后,最后确认一下 nginx -V :
1 2 3 4 5 | linux–gz215:~ # /usr/local/nginx/sbin/nginx -V nginx version: nginx/1.6.0 built by gcc 4.1.2 20070115 (prerelease) (SUSE Linux) TLS SNI support enabled configure arguments: —user=www —group=www —prefix=/usr/local/nginx —with–http_ssl_module —with–openssl=/usr/local/src/openssl–1.0.1c —with–http_stub_status_module —with–pcre —with–pcre=/usr/local/src/pcre–8.21 —with–zlib=/usr/local/src/zlib–1.2.8 |
正常了,平滑升级成功!
二、纯手动平滑升级
纯手动模式,指的是在最后做迁移的时候,全部使用手动命令来搞定,避免编译可能存在不一致的参数啥的。
实际上,在 make 之后,我们可以查看 nginx 源码目录下的 Makefile 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | default: build clean: rm –rf Makefile objs build: $(MAKE) –f objs/Makefile $(MAKE) –f objs/Makefile manpage install: $(MAKE) –f objs/Makefile install upgrade: /usr/local/nginx/sbin/nginx –t kill –USR2 `cat /usr/local/nginx/logs/nginx.pid` sleep 1 test –f /usr/local/nginx/logs/nginx.pid.oldbin kill –QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin` |
所以,说白了纯手动就是执行 upgrade 标签下的命令行而已,实际上只要确认 Makefile 下的命令路径都是正确的,用命令自动迁移是没有任何问题的。
总是有人会不放心的,喜欢手动一步一步的搞定,我也来整理下纯手动步骤:
①~③和半自动一样,按常规步骤先编译 nginx,不过只执行到 make 就打住,然后将旧的 sbin 下的 nginx 文件移走,再将编译得到的 objs 目录下的 nginx 文件放到原来的 sbin 目录。
④、测试新版本的 nginx 是否正常:
1 2 3 | [root@Mars_Server nginx–1.6.0]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok #OK,没有问题! nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful |
⑤、给旧 nginx 发送平滑迁移信号(若不清楚 pid 路径就用可用命令(2)):
1 2 3 4 5 | #可用命令(1): kill –USR2 `cat /usr/local/nginx/logs/nginx.pid` #可用命令(2): kill –USR2 `ps aux | grep “nginx: master process” | grep –v grep | awk ‘{print $2}’` |
Ps:后面其实就是旧 nginx 的 pid,所以先用 ps aux 找到正在运行的 nginx 主进程 pid,再执行 kill -USR2 PID 值亦可。
⑥、等待旧版本 Nginx 的 pid 变为 oldbin(执行如下命令查看是否生成)
1 | test –f /usr/local/nginx/logs/nginx.pid.oldbin && echo OK! |
⑦、 从容关闭旧版本的 Nginx 进程
1 | kill –WINCH `cat /usr/local/nginx/log/nginx.oldbin` |
此时,旧的工作进程就都会慢慢随着任务执行完毕而退出,新版的 Nginx 的工作进程会逐渐取代旧版工作进程。
⑧、此时,不重载配置启动旧工作进程(个人感觉是为了将任务完全切换到新的 nginx 上)
1 | kill –HUP `cat /url/local/nginx/log/nginx.oldbin` |
⑨、结束工作进程,完成此次升级操作:
1 | kill –QUIT `cat /usr/local/nginx/log/nginx.oldbin` |
⑩、最后,验证 nginx 是否升级成功:
1 2 3 4 5 | linux–gz215:~ # /usr/local/nginx/sbin/nginx -V nginx version: nginx/1.6.0 #没问题 built by gcc 4.1.2 20070115 (prerelease) (SUSE Linux) TLS SNI support enabled configure arguments: —user=www —group=www —prefix=/usr/local/nginx —with–http_ssl_module —with–openssl=/usr/local/src/openssl–1.0.1c —with–http_stub_status_module —with–pcre —with–pcre=/usr/local/src/pcre–8.21 —with–zlib=/usr/local/src/zlib–1.2.8 |
特意测试了下纯手动的做法,下面是我的操作记录,仅供参考:
为了验证平滑升级确实不影响在线业务,我特意在升级的时候,利用 ab 命令一直在发送请求:
1 | ab –n1000000 –c10 http://domain.com/ |
直到升级完成,使用 ctrl +C 终止并查看 ab 结果,可以发现几十万次的请求全部成功,没有失败!证明平滑升级的可行性!可惜忘记了截图,感兴趣的童鞋可以自行测试下!
好了,关于 nginx 的平滑升级和在线新增模块的操作记录就到这里结束了,希望对你有所帮助。