精品免费在线观看-精品欧美-精品欧美成人bd高清在线观看-精品欧美高清不卡在线-精品欧美日韩一区二区

17站長(zhǎng)網(wǎng)

nginx平滑重啟的實(shí)現(xiàn)方法

2022-10-6 13:49| 查看: 1502 |來(lái)源: 互聯(lián)網(wǎng)

在服務(wù)器開(kāi)發(fā)過(guò)程中,難免需要重啟服務(wù)加載新的代碼或配置,如果能夠保證server重啟的過(guò)程中服務(wù)不間斷,那重啟對(duì)于業(yè)務(wù)的影響可以降為0。最近調(diào)研了一下nginx平 ...

一、背景

在服務(wù)器開(kāi)發(fā)過(guò)程中,難免需要重啟服務(wù)加載新的代碼或配置,如果能夠保證server重啟的過(guò)程中服務(wù)不間斷,那重啟對(duì)于業(yè)務(wù)的影響可以降為0。最近調(diào)研了一下nginx平滑重啟,覺(jué)得很有意思,記錄下來(lái)供有興趣的同學(xué)查閱。

二、重啟流程

  •  重啟意味著新舊接替,在交接任務(wù)的過(guò)程中勢(shì)必會(huì)存在新舊server并存的情形,因此,重啟的流程大致為:

    • 啟動(dòng)新的server

    • 新舊server并存,兩者共同處理請(qǐng)求,提供服務(wù)

    • 舊的server處理完所有的請(qǐng)求之后優(yōu)雅退出

  • 這里,最主要的問(wèn)題在于如何保證新舊server可以并存,如果重啟前后的server端口一致,如何保證兩者可以監(jiān)聽(tīng)同一端口。

 三、nginx實(shí)現(xiàn)

為了驗(yàn)證nginx平滑重啟,筆者首先嘗試nginx啟動(dòng)的情形下再次開(kāi)啟一個(gè)新的server實(shí)例,結(jié)果如圖:

很明顯,重新開(kāi)啟server實(shí)例是行不通的,原因在于新舊server使用了同一個(gè)端口80,在未開(kāi)始socket reuseport選項(xiàng)復(fù)用端口時(shí),bind系統(tǒng)調(diào)用會(huì)出錯(cuò)。nginx默認(rèn)bind重試5次,失敗后直接退出。而nginx需要監(jiān)聽(tīng)I(yíng)PV4地址0.0.0.0和IPV6地址[::],故圖中打印出10條emerg日志。

接下來(lái)就開(kāi)始嘗試平滑重啟命令了,一共兩條命令:

kill -USR2 `cat /var/run/nginx.pid`
kill -QUIT `cat /var/run/nginx.pid.oldbin`

第一條命令是發(fā)送信號(hào)USR2給舊的master進(jìn)程,進(jìn)程的pid存放在/var/run/nginx.pid文件中,其中nginx.pid文件路徑由nginx.conf配置。

第二條命令是發(fā)送信號(hào)QUIT給舊的master進(jìn)程,進(jìn)程的pid存放在/var/run/nginx.pid.oldbin文件中,隨后舊的master進(jìn)程退出。

那么問(wèn)題來(lái)了,為什么舊的master進(jìn)程的pid存在于兩個(gè)pid文件之中?事實(shí)上,在發(fā)送信號(hào)USR2給舊的master進(jìn)程之后,舊的master進(jìn)程將pid重命名,原先的nginx.pid文件rename成nginx.pid.oldbin。這樣新的master進(jìn)行就可以使用nginx.pid這個(gè)文件名了。

先執(zhí)行第一條命令,結(jié)果如圖:

不錯(cuò),新舊master和worker進(jìn)程并存了。 再來(lái)第二條命令,結(jié)果如圖:

如你所見(jiàn),舊的master進(jìn)程8527和其worker進(jìn)程全部退出,只剩下新的master進(jìn)程12740。

不由得產(chǎn)生困惑,為什么手動(dòng)開(kāi)啟一個(gè)新的實(shí)例行不通,使用信號(hào)重啟就可以達(dá)到。先看下nginx log文件:

除了之前的錯(cuò)誤日志,還多了一條notice,意思就是繼承了sockets,fd值為6,7。 隨著日志翻看nginx源碼,定位到nginx.c/ngx_exec_new_binary函數(shù)之中,

ngx_pid_t
ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
{
  ...
  ctx.path = argv[0];
  ctx.name = "new binary process";
  ctx.argv = argv;
  n = 2;
  env = ngx_set_environment(cycle, &n);
...
  var = ngx_alloc(sizeof(NGINX_VAR)
          + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
          cycle->log);
...
  p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
  ls = cycle->listening.elts;
  for (i = 0; i < cycle->listening.nelts; i++) {
    p = ngx_sprintf(p, "%ud;", ls[i].fd);
  }
  *p = '\0';
  env[n++] = var;
...
  env[n] = NULL;
...
  ctx.envp = (char *const *) env;
  ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
  if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
    ...
    return NGX_INVALID_PID;
  }
  pid = ngx_execute(cycle, &ctx);
  if (pid == NGX_INVALID_PID) {
    if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
      == NGX_FILE_ERROR)
    {
      ...
    }
  }
...
  return pid;
}

函數(shù)的流程為

  1.  將舊的master進(jìn)程監(jiān)聽(tīng)的所有fd,拷貝至新master進(jìn)程的env環(huán)境變量NGINX_VAR。

  2. rename重命名pid文件

  3. ngx_execute函數(shù)fork子進(jìn)程,execve執(zhí)行命令行啟動(dòng)新的server。

  4. 在server啟動(dòng)流程之中,涉及到環(huán)境變量NGINX_VAR的解析,ngx_connection.c/ngx_add_inherited_sockets具體代碼為:

static ngx_int_t
ngx_add_inherited_sockets(ngx_cycle_t *cycle)
{
...
  inherited = (u_char *) getenv(NGINX_VAR);
  if (inherited == NULL) {
    return NGX_OK;
  }
  if (ngx_array_init(&cycle->listening, cycle->pool, 10,
            sizeof(ngx_listening_t))
    != NGX_OK)
  {
    return NGX_ERROR;
  }
  for (p = inherited, v = p; *p; p++) {
    if (*p == ':' || *p == ';') {
      s = ngx_atoi(v, p - v);
      ...
      v = p + 1;
      ls = ngx_array_push(&cycle->listening);
      if (ls == NULL) {
        return NGX_ERROR;
      }
      ngx_memzero(ls, sizeof(ngx_listening_t));
      ls->fd = (ngx_socket_t) s;
    }
  }
  ...
  ngx_inherited = 1;
  return ngx_set_inherited_sockets(cycle);
}

函數(shù)流程為:

解析環(huán)境變量NGINX_VAR的值,獲取fd存入數(shù)組

fd對(duì)應(yīng)的socket設(shè)為ngx_inherited,保存這些socket的信息。

也就是說(shuō),新的server壓根就沒(méi)重新bind端口listen,這些fd狀態(tài)和值都是新的master進(jìn)程fork時(shí)帶過(guò)來(lái)的,新的master進(jìn)程監(jiān)聽(tīng)處理繼承來(lái)的文件描述符即可,這里比較關(guān)鍵的一點(diǎn)在于listen socket文件描述符通過(guò)ENV傳遞。

本文最后更新于 2022-10-6 13:49,某些文章具有時(shí)效性,若有錯(cuò)誤或已失效,請(qǐng)?jiān)诰W(wǎng)站留言或聯(lián)系站長(zhǎng):17tui@17tui.com
·END·
站長(zhǎng)網(wǎng)微信號(hào):w17tui,關(guān)注站長(zhǎng)、創(chuàng)業(yè)、關(guān)注互聯(lián)網(wǎng)人 - 互聯(lián)網(wǎng)創(chuàng)業(yè)者營(yíng)銷(xiāo)服務(wù)中心

免責(zé)聲明:本站部分文章和圖片均來(lái)自用戶(hù)投稿和網(wǎng)絡(luò)收集,旨在傳播知識(shí),文章和圖片版權(quán)歸原作者及原出處所有,僅供學(xué)習(xí)與參考,請(qǐng)勿用于商業(yè)用途,如果損害了您的權(quán)利,請(qǐng)聯(lián)系我們及時(shí)修正或刪除。謝謝!

17站長(zhǎng)網(wǎng)微信二維碼

始終以前瞻性的眼光聚焦站長(zhǎng)、創(chuàng)業(yè)、互聯(lián)網(wǎng)等領(lǐng)域,為您提供最新最全的互聯(lián)網(wǎng)資訊,幫助站長(zhǎng)轉(zhuǎn)型升級(jí),為互聯(lián)網(wǎng)創(chuàng)業(yè)者提供更加優(yōu)質(zhì)的創(chuàng)業(yè)信息和品牌營(yíng)銷(xiāo)服務(wù),與站長(zhǎng)一起進(jìn)步!讓互聯(lián)網(wǎng)創(chuàng)業(yè)者不再孤獨(dú)!

掃一掃,關(guān)注站長(zhǎng)網(wǎng)微信

大家都在看

熱門(mén)排行

    最近更新

      返回頂部
      主站蜘蛛池模板: 亚洲 欧美 手机 在线观看 | 亚洲综合视频网 | 亚洲欧美在线观看91偷拍 | 欧美一级性生活视频 | 一区二区三区四区国产 | igao视频天堂| 性做爰片免费视频毛片中文ilo | chinese乱子伦videos | 成人综合影院 | 好叼操这里只有精品 | 亚洲aⅴ久久久噜噜噜噜 | 亚洲精品区在线播放一区二区 | 成人在线你懂的 | 久久精品视频2 | 黄色片三| a三级毛片| 国产手机精品自拍视频 | 亚洲国产成人久久一区二区三区 | 国产亚洲欧洲一区二区三区 | 亚洲精选在线观看 | 欧美日韩a级片 | 亚洲欧洲日韩天堂无吗 | 91亚洲精品一区二区在线观看 | 久久精品国产亚洲麻豆小说 | 日韩成人在线观看视频 | 日本特黄特黄刺激大片免费 | 中文字幕在线观 | 国产成人精品视频一区二区不卡 | 免费观看在线永久免费xx视频 | 亚洲精品欧美 | 热伊人99re久久精品最新地 | 日韩精品国产一区 | fc2成人免费人成在线观看播放 | 天天拍拍天天爽免费视频 | 欧美色爱综合网 | 麻豆国产精品va在线观看不卡 | 欧美+日本+国产+在线观看 | 国产欧美在线观看视频 | 一级毛片免费不卡 | 91精品在线看 | 欧美一级aa免费毛片 |