방법은 부드러운 재기동의 nginx를 달성

한 배경

서버 개발 과정에서 우리는 필연적으로 서버가 다시 시작하는 동안 서비스가 중단되지 않도록하는 경우, 새로운 코드 나 구성을로드하도록 서비스를 다시 시작해야합니다 0으로 감소 될 수있다 비즈니스에 미치는 영향에 대해 다시 시작합니다. 최근의 연구는 GR의 nginx 조금보기에 관심있는 학생들에 대한 기록은 매우 흥미로운 찾을 수 있습니다.

둘째, 재시작 과정

  •  성공 이전 및 새 수단을 다시 시작, 전환 작업 중에 공존 할 수밖에 없다 과거와 현재 서버의 경우가 있기 때문에, 다시 시작하는 대략입니다 :
    • 새 서버를 시작합니다
    • 함께 서비스를 제공하기 위해 요청을 처리 이전 및 새 서버의 공존,
    • 모든 처리 후 기존 서버 우아한 종료를 요청
  • 여기서 가장 큰 문제는 확인하는 방법입니다 이전 및 새 서버 캔 공존, 이전과 다시 시작한 후 동일한 서버 포트, 방법 모두 동일한 포트에서 수신 할 수 있는지 확인합니다.

 세, 달성의 nginx

nginx를 GR을 확인하려면, 내가 먼저 다시, 결과가 표시되는 서버의 새로운 인스턴스를 시작 Nginx에 케이스를 열려고 :

분명히, 이전 및 새 서버가 80 포트를 사용하기 때문에 포트를 다중화 소켓 reuseport 옵션에서 시작되지 않았다 서버 인스턴스 가능하지를 다시 열고, 바인딩 시스템 호출 오류. nginx를 기본 바인딩은 다섯 번, 실패 후 직접 종료를 시도합니다. Nginx의 IPv4 주소 및 모니터링의 필요성 및 IPV6 주소 0.0.0.0 [::], 그래서도. (10) 인쇄 로그 EMERG 그.

그리고는 다시 시작 명령을 두 명령의 전체를 부드럽게하려고하기 시작했다 :

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

첫 번째 명령 신호는 이전 마스터 프로세스 USR2 프로세스 파일 nginx.pid nginx.conf로 구성된 파일 경로에 저장된 PID /var/run/nginx.pid로 전송된다.

두 번째 명령은 다음 파일에 저장 /var/run/nginx.pid.oldbin PID 프로세스 이전 마스터 프로세스가 종료 이전 마스터 프로세스에 신호를 QUIT 보내는 것입니다.

질문은 그래서, 왜 PID 이전 마스터 프로세스는 두 PID 파일에 존재? 사실, 이전 마스터 USR2 프로세스에 신호를 전송 한 후, 이전 마스터 과정은 nginx.pid.oldbin에 nginx.pid 원본 파일 이름 바꾸기 이름을 변경 PID. 이러한 새로운 마스터가 nginx.pid의 파일 이름을 사용할 수 있었다.

첫 번째 명령을 실행 먼저, 그 결과를 도시 :

예, 이전 및 새 마스터의 공존 및 작업자 프로세스. 두 번째 명령은 다시 그 결과를 도시 :

당신이 볼 수 있듯이, 기존의 마스터 프로세스 8527과 작업자 프로세스 모두는 새로운 마스터 프로세스 12,740 떠나, 종료합니다.

도움이되지 수도 있지만 수동으로하지 작업, 다시 시작 신호를 달성 할 수 사용합니까 새로운 인스턴스를 열 이유에 혼동. 의 nginx 로그 파일에서 봐 :

오류 로그에 추가하기 전에, 더 통지보다 6,7의 상속 소켓, FD 값을 의미한다. 로그 모습 Nginx의 소스 nginx.c / ngx_exec_new_binary 함수에 위치 된 바와 같이,

?
1
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)
(41)
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;
}

프로세스 기능입니다

  1.  모든 오래된 마스터 프로세스 모니터 (FD)와 새 마스터 과정 ENV 환경 변수 NGINX_VAR에 복사.
  2. 이름 바꾸기 이름 바꾸기 파일 PID
  3. ngx_execute 기능 포크의 자식 프로세스는 execve 새 서버를 시작하려면 명령 줄을 실행합니다.
  4. 서버 시작 프로세스 중, ngx_connection.c / ngx_add_inherited_sockets 특정 코드는 환경 변수 NGINX_VAR를 분석 포함 :
?
1
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
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);
}

函数流程为:

解析环境变量NGINX_VAR的值,获取fd存入数组

fd对应的socket设为ngx_inherited,保存这些socket的信息。

也就是说,新的server压根就没重新bind端口listen,这些fd状态和值都是新的master进程fork时带过来的,新的master进程监听处理继承来的文件描述符即可,这里比较关键的一点在于listen socket文件描述符通过ENV传递。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

추천

출처www.cnblogs.com/zhuyeshen/p/12061495.html