`
cloudtech
  • 浏览: 4595020 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

nginx多进程模型之热代码平滑升级

 
阅读更多

平滑升级的主要过程包括一下步骤:

1. 新代码make执行完后,这里不用在make install 了,接下来重名/sbin/nginx为nginx.old

# mv /usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx.old

2. 复制编译后objs目录下的nginx文件到nginx的安装目录sbin/下

# cp objs/nginx /usr/local/nginx/sbin/

3. 让nginx把nginx.pid文件修改成nginx.pid.oldbin,随即启动nginx,实现不间断

# kill -USR2 `cat/usr/local/nginx/nginx.pid`

# kill -QUIT `cat/usr/local/nginx/nginx.pid.oldbin`

当然,官方上有个更加详细的过程,包括了取消升级、新旧代码同时保留等操作,这里我们主要看上述给出简单升级的实现。

http://wiki.nginx.org/ChsCommandLine

这里我们主要看步骤3:

nginx里面讲USR2信号定义成NGX_CHANGEBIN_SIGNAL。

#define NGX_CHANGEBIN_SIGNAL USR2

它的处理函数,跟其他的一样信号一样,使用了ngx_signal_handler。这个函数在配置热加载的那篇文章里已经接触过了,我们在执行kill -USR2 `cat /usr/local/nginx/nginx.pid`时,master进程会得到信号,因为pid文件中记录了master进程的pid。

// ngx_process这个变量记录了接收到信号的进程类型,这里很明显是master process(因为通过master的pid发出的信号)
switch (ngx_process) {

    case NGX_PROCESS_MASTER:
    case NGX_PROCESS_SINGLE:
        switch (signo) {
	…
        case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
            /* 这里给出了详细的注释,更通俗一点来讲,就是说,进程现在是一个
	     * master(新的master进程),但是当他的父进程old master还在运行的话,
             * 这时收到了USR2信号,我们就忽略它,不然就成了新master里又要生成
             * master。。。另外一种情况就是,old master已经开始了生成新master的过程
             * 中,这时如果又有USR2信号到来,那么也要忽略掉。。。(不知道够不够通俗=.=)
             */
            if (getppid() > 1 || ngx_new_binary > 0) {

                /*
                 * Ignore the signal in the new binary if its parent is
                 * not the init process, i.e. the old binary's process
                 * is still running.  Or ignore the signal in the old binary's
                 * process if the new binary's process is already running.
                 */

                action = ", ignoring";
                ignore = 1;
                break;
            }
            // 最重要的操作在这里,通过将ngx_change_binary置为1,来告诉master
            // 应该去启动一个新的实例了,也就是说,master里面在检测到这个变量为// 1时,就会做新nginx实例的生成工作了
            ngx_change_binary = 1;
            action = ", changing binary";
            break;		…
       }
}

新实例的产生在ngx_master_process_cycle函数里处理,这个函数大家应该很熟悉,它主要是在一个for循环里来监控各种信号和状态,来控制系统和工作进程。

for ( ;; ) {

    …

    //上面已经提过,USR2的信号处理里面,会将ngx_change_binary置为1,这样在master循环里,就可以做处理了。

    if(ngx_change_binary) {

        ngx_change_binary = 0;

        ngx_new_binary = ngx_exec_new_binary(cycle,ngx_argv);

    }
    …
}

在函数ngx_exec_new_binary里面,主要的工作就是将listen的fd,放到环境变量中,格式为:NGINX=fd1;fd2;fd3……(这个后面讲!),然后将nginx.pid改成为nginx.pid.oldbin,最后就是通过ngx_execute,其实就是execve来启动新实例。。。

这里有个地方要提一下,就是上面提到的listen fd,它被放到了环境变量中,目的就是在新实例启动的过程中,通过ngx_add_inherited_sockets来拿到之前的listen fd,重新使用,之所以要这样,是因为新的实例是通过fork+execve来产生,不是跟简单fork之后子进程那样直接就可以拿到这个父进程的listen fd来用。

在步骤3中,我们通过发送QUIT信号将旧的进程来关闭。涉及的流程如下:

// 收到SIGCHLD,意味着子进程(即worker 进程),会将ngx_reap置1,这样在master中可以
// 检测到这个变量的值,让后重启子进程。。。

if (ngx_reap) {

    ngx_reap = 0;

    live = ngx_reap_children(cycle);

}

// live为1表示有子进程在运行,为0代表,所有子进程都退出了,这是如果有退出之类的// 信号,那么就直接exit退出了。

if (!live && (ngx_terminate ||ngx_quit)) {

    ngx_master_process_exit(cycle);

}

…

// 正式处理QUIT信号

if (ngx_quit) {

    //通知worker进程,处理完自己的事务之后自动退出。

    ngx_signal_worker_processes(cycle,ngx_signal_value(NGX_SHUTDOWN_SIGNAL));

    // 之后的处理就是关闭listenfd,不在监听连接。
    …
}

这里简单说下worker进程在接收到父进程通知的NGX_SHUTDOWN_SIGNAL会,将ngx_quit置1,当然对于ngx_quit的处理,在worker和master是不一样的,需要区分,这也就是ngx_process类型的作用啦。后面worker进程会停止关闭继承的listenfd,同时accpet新连接的行为也消失了,然后呢,进程会等到已经”hold”的连接全部处理之后再退出,做到善始善终!

分享到:
评论

相关推荐

    nginx平滑升级

    nginx平滑升级

    nginx1.8平滑升级

    nginx1.8版本平滑升级,本文档用于nginx1.8平滑升级到nginx1.11.2文档

    教你平滑升级Nginx版本.docx

    LINUX操作系统、Nginx Web服务器、MySQL/MariaDB数据库服务器、PHP/Python/Perl... 等开发语言。

    从nginx角度看服务器多进程模型设计

    从nginx角度看服务器多进程模型设计,这是一些用来分析nginx的设计思路的资料,从中可以得到很多启发。

    nginx的平滑升级

    nginx平滑升级,不停止在线应用,支持升级到1.2.4版本

    CentOS 7 nginx平滑升级.pdf

    CentOS 7 nginx平滑升级

    Centos7环境下Nginx版本升级方式及步骤

     源码平滑升级升级:本方式适用于使用源码安装nginx的方式,通过替换nginx二进制文件完成升级,原理就是Ngnix中的进程分为两类,一类是master进程(主进程),一类是worker进程(工作进程),首先我们先会替换...

    Nginx 内存模型.

    Nginx 内存模型.

    centos7-Nginx从1.12平滑升级到1.14

    如标题所述本文讲述了centos7-Nginx如何从1.12平滑升级到1.14。

    Nginx平滑升级的详细操作方法

    一、平滑升级概述Nginx方便地帮助我们实现了平滑升级。其原理简单概括,就是:(1)在不停掉老进程的情况下,启动新进程。(2)老进程负责处理仍然没有处理完的请求,但不再接受处理请求。(3)新进程接受新请求。...

    nginx 的平滑升级.md

    nginx 的平滑升级.md

    nginx编译安装后对nginx进行平滑升级的方法

    nginx编译安装后用了一段时间后发现当前版本有漏洞或需要新的功能时就需要对当前nginx版本进行版本升级,但又不能影响正常的使用,所以这时就需到对nginx的平滑升级,更新到最新版本了。 本文演示的是nginx-1.13.6...

    Nginx 代码研究

    我们发现目前学习nginx的例子很少,主要是emiller的模块开发介绍这篇文章, 但是单独研究这篇文章发现很多晦涩难懂的地方,而目前还没有其他更好的文章来对这些地方做解释, 有些东西必须要通过源代码的研读才可以...

    重启或杀掉Nginx进程后丢失nginx.pid的解决办法

    安装SSL证书时,强行杀掉了Nginx的进程,就再也没起来: Restarting nginx daemon: nginxcat: /usr/local/nginx/logs/nginx.pid: No such file or directorykill: usage: kill [-s sigspec | -n signum | -sigspec] ...

    升级gitlab中nginx版本.docx

    配置系统nginx,使gitlab使用系统自带的nginx,配置端口号,禁止使用自身绑定的nginx,

    NGINX 0.1版代码

    这是NGINX的0.1版源代码,模块结构相对简单,适用于有志研究NGINX代码的童鞋进行学习。

    Nginx笔记-Nginx中进程结构及使用Linux信号量管理

    热部署、平滑升级、开源及二次开发、高并发高性能、扩展性好、异步非阻塞的事件驱动模型 Nginx是多进程结构: 主进程Master Process管理如下几个进程: CM(Cacah Manager)、CL(Cacah Loader)、Worker Process...

    详解nginx平滑升级的过程

    主要介绍了详解nginx平滑升级的过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    1分钟搞定Nginx版本的平滑升级与回滚的方法

    今天,我们来聊一聊,在企业实际生产环境中经常遇到的一个情况,升级Nginx到新的版本和如何回滚至旧版本。 1、环境介绍 今天准备的两个nginx版本如下: [root@nginx ~]# cd /download/nginx/ [root@nginx nginx]# ...

Global site tag (gtag.js) - Google Analytics