Nginx源碼學習——優(yōu)雅的停止Nginx服務

命令

nginx -s quitkill -s SIGQUIT <nginx master pid> 可以優(yōu)雅的關閉服務。它們都是通過發(fā)送信號實現(xiàn)的。具體見——向master進程發(fā)送信號。

具體過程

向master進程發(fā)送信號 一文可知,捕捉到信號并處理后,master進程被喚醒,它將檢測被信號處理函數(shù)改寫過的全局變量的值,進而決定下一步的執(zhí)行。
當在終端執(zhí)行 nginx -s quitkill -s SIGQUIT <nginx master pid>命令后,全局變量ngx_quit被置位為1;

//ngx_signal_handler函數(shù)代碼片段

case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
            ngx_quit = 1;
            action = ", shutting down";
            break;

master進程循環(huán)內(nèi)部,與quit相關代碼如下所示。
首先,調用ngx_signal_worker_processed函數(shù),第二個參數(shù)ngx_signal_value(NGX_SHUTDOWN_SIGNAL)實際上就是SIGQUIT信號,該函數(shù)將通知所有子進程終止。
其次,關閉所有監(jiān)聽socket,并復位cycle指針指向的配置項結構體的成員listening,該成員與監(jiān)聽socket有關。

if (ngx_quit) {
   ngx_signal_worker_processes(cycle,ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
 
            ls = cycle->listening.elts;
            for (n = 0; n < cycle->listening.nelts; n++) {
                if (ngx_close_socket(ls[n].fd) == -1) {
                    ngx_log_error(...)
                }
            }
            cycle->listening.nelts = 0;

            continue;
        }

下面看ngx_signal_worker_processed函數(shù)

//片段1

static void
ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
{
    ......
    ngx_channel_t ch;

    switch (signo) {

    case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
        ch.command = NGX_CMD_QUIT;
        break;

    case ngx_signal_value(NGX_TERMINATE_SIGNAL):
        ch.command = NGX_CMD_TERMINATE;
        break;

    case ngx_signal_value(NGX_REOPEN_SIGNAL):
        ch.command = NGX_CMD_REOPEN;
        break;

    default:
        ch.command = 0;
    }
    ......
}

ngx_signal_worker_processed函數(shù)中有一個重要的結構體ngx_channel_t,具體如下:

typedef struct {
    ngx_uint_t  command;//傳遞的TCP消息中的命令
    ngx_pid_t   pid; //一般是發(fā)送命令方的進程id
    ngx_int_t   slot;//表示發(fā)送命令方在ngx_processes進程數(shù)組間的序號
    ngx_fd_t    fd;//通信的套接字句柄
} ngx_channel_t;

通過該結構體和與其相關的三個函數(shù)實現(xiàn)master進程與worker進程的通信,具體見 master與worker的通信機制 一文。先簡單介紹下這三個函數(shù):
ngx_open_channel——建立通信通道
ngx_write_channel——向另一進程發(fā)送消息
ngx_read_channel——讀取所獲得的消息

當判斷信號為 ngx_signal_value(NGX_SHUTDOWN_SIGNAL),即SIGQUIT后,令ch.command = NGX_CMD_QUIT,調用ngx_write_channel函數(shù)將給命令發(fā)送給子進程。

  //通過CHANNEL發(fā)送命令給待終止的子進程,子進程調用ngx_channel_handler 處理
  //由于是非阻塞socket,函數(shù)返回前,命令將被傳遞給子進程
  if (ch.command) {
      if (ngx_write_channel(ngx_processes[i].channel[0],
                                  &ch, sizeof(ngx_channel_t), cycle->log)
          == NGX_OK)
      {
            if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
                 ngx_processes[i].exiting = 1;
            }

            continue;
       }
   }
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 本文系轉載》》》》》》》》》》》》》》》》 編者按:高可用架構分享及傳播在架構領域具有典型意義的文章,本文由陳科在...
    demop閱讀 8,377評論 0 7
  • daemon: Linux Daemon(守護進程)是運行在后臺的一種特殊進程。它獨立于控制終端并且周期性地執(zhí)行某...
    燁哥閱讀 3,696評論 0 6
  • 第一章 Nginx簡介 Nginx是什么 沒有聽過Nginx?那么一定聽過它的“同行”Apache吧!Ngi...
    JokerW閱讀 33,039評論 24 1,002
  • 什么是Nginx? Nginx是一個高性能的HTTP和反向代理服務器,也是一個IMAP/POP3/SMTP服務器N...
    jiangmo閱讀 2,650評論 1 9
  • 讓人憐憫的玻璃 是望不透的 給人生路或是以死路 縫隙之大小無所查證 只晨曦出來代我跳過一跳 才懂無能為力也無奈 盡...
    何五塵閱讀 329評論 0 0

友情鏈接更多精彩內(nèi)容