• Nginx得知——流程模型(worker流程)


    流程模型

    worker流程

            master进程模型核心函数ngx_master_process_cycle()中调用了创建子进程函数ngx_start_worker_processes(),该函数源代码例如以下

    static void
    ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
    {
        ngx_int_t      i;
        ngx_channel_t  ch;
    
        ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
    
        ch.command = NGX_CMD_OPEN_CHANNEL;
    	/
        for (i = 0; i < n; i++) {
    		/*ngx_spawn_process方法调用fork函数创建进程运行ngx_worker_process_cycle()函数,该函数是worker进程模型的核心*/
            ngx_spawn_process(cycle, ngx_worker_process_cycle,
                              (void *) (intptr_t) i, "worker process", type);
    		/*
    		在ngx_spawn_process创建好一个worker进程返回后,master进程就将worker进程的pid、worker
    		进程在ngx_processes数组中的位置及channel[0]传递给前面已经创建好的worker进程。然后继续
    		循环開始创建下一个worker进程。

    */ ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); } }


            在剖析ngx_worker_process_cycle是怎样工作的之前我们了解master进程和worker进程之间的通信方式:master进程是监控进程。对worker进程监控和管理。master进程採用的是信号管理worker进程。worker进程收到信号时,信号处理函数ngx_signal_handler()就会运行。

            对于worker进程的工作方法ngx_worker_process_cycle来说,它主要关注4个全局标志位:

            sig_atomic_t    ngx_terminate;        //强制关闭进程

            sig_atomic_t    ngx_quit;                 //优雅地关闭进程(有唯一一段代码会设置它。就是接受到QUIT信号。ngx_quit仅仅有在首次设置为1,时,才会将ngx_exiting置为1)

           ngx_uint_t         ngx_exiting;            //退出进程标志位

           sig_atomic_t    ngx_reopen;          //又一次打开全部文件

            当中ngx_terminate、ngx_quit 、ngx_reopen都将由ngx_signal_handler依据接受到的信号来设置,例如以下表所看到的。

    ngx_exiting标志位仅由ngx_worker_cycle方法在退出时作为标志位使用。

    信号

    相应进程中全局标志位变量

    意义

    QUIT

    ngx_quit

    优雅关闭进程

    TERM或者INT

    ngx_terminate

    强制关闭进程

    USR1

    ngx_reopen

    又一次打开全部文件

             如今我们来剖析ngx_worker_process_cycle()函数。能够对比下图来理解源码:

     

          

    static void
    ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
    {
        ngx_int_t worker = (intptr_t) data;
    
        ngx_uint_t         i;
        ngx_connection_t  *c;
    
        ngx_process = NGX_PROCESS_WORKER;
    	/*worker进程进入工作循环之前的初始化工作*/
        ngx_worker_process_init(cycle, worker);
    
        ngx_setproctitle("worker process");
    
    #if (NGX_THREADS)
        {
        ngx_int_t         n;
        ngx_err_t         err;
        ngx_core_conf_t  *ccf;
    
        ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
    
        if (ngx_threads_n) {
            if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
                == NGX_ERROR)
            {
                /* fatal */
                exit(2);
            }
    
            err = ngx_thread_key_create(&ngx_core_tls_key);
            if (err != 0) {
                ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
                              ngx_thread_key_create_n " failed");
                /* fatal */
                exit(2);
            }
    
            for (n = 0; n < ngx_threads_n; n++) {
    
                ngx_threads[n].cv = ngx_cond_init(cycle->log);
    
                if (ngx_threads[n].cv == NULL) {
                    /* fatal */
                    exit(2);
                }
    
                if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid,
                                      ngx_worker_thread_cycle,
                                      (void *) &ngx_threads[n], cycle->log)
                    != 0)
                {
                    /* fatal */
                    exit(2);
                }
            }
        }
        }
    #endif
    	
        for ( ;; ) {
    		/*ngx_exiting为1。在開始准备关闭worker金曾*/
            if (ngx_exiting) {
    
                c = cycle->connections;
    			
                for (i = 0; i < cycle->connection_n; i++) {
    
                    /* THREAD: lock */
    				/* 依据当前ngx_cycle_t中全部正在处理的连接。调用它们相应的关闭连接处理方法 */
                    if (c[i].fd != -1 && c[i].idle) {
                        c[i].close = 1;
                        c[i].read->handler(c[i].read);
                    }
                }
    			/*
    			若ngx_event_timer_rbtree红黑树不为空表示还有事件须要处理。
    			否则,调用ngx_worker_process_exit,以调用全部模块的exit_process方法,销毁内存池
    			*/
                if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
                {
                    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
    
                    ngx_worker_process_exit(cycle);
                }
            }
    
            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
    
            ngx_process_events_and_timers(cycle);
    		/*强制结束进程*/
            if (ngx_terminate) {
    			
                ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
    			/*调用全部模块的exit_process方法,销毁内存池*/
                ngx_worker_process_exit(cycle);
            }
    		/*优雅的关闭基进程*/
            if (ngx_quit) {
                ngx_quit = 0;
                ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
                              "gracefully shutting down");
                ngx_setproctitle("worker process is shutting down");
    
                if (!ngx_exiting) {
    				/*关闭全部的监听句柄并设置ngx_exiting标志*/
                    ngx_close_listening_sockets(cycle);
                    ngx_exiting = 1;
                }
            }
    		/*又一次打开全部文件*/
            if (ngx_reopen) {
                ngx_reopen = 0;
                ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
                ngx_reopen_files(cycle, -1);
            }
        }
    }
    

    转载请注明出处,谢谢~~

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    git命令
    svg学习系列02-简单的svg图形和线条
    svg学习系列01-svg简介
    jQuery分页插件
    svg简介
    css3选择器
    sublime使用
    HTML5新特性
    html新的语义化标签和表单控件
    DOM详解
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4874825.html
Copyright © 2020-2023  润新知