nginx 소스 코드 분석 --- upstream 설정 분석

10741 단어 nginx
nignx 설정 파일 을 분석 할 때 설정 을 만 났 을 때 어떤 일 을 합 니까?
upstream test.balancer.com {
			1.1.1.1:80;
			2.2.2.2:80;
}

1. upstream 설정 을 저장 하 는 3 대 구조 체
우선 upstream 설정 의 저장 문 제 를 해결 해 야 합 니 다. nginx 는 ngx 를 통 해http_upstream_main_conf_t,ngx_http_upstream_srv_conf_t,ngx_http_upstream_server_t 세 개의 구조 체 는 upstream 설정 을 저장 합 니 다.그 중 ngxhttp_upstream_main_conf_t 의 정 의 는 다음 과 같다.
typedef struct {
    ngx_hash_t                       headers_in_hash;
    ngx_array_t                      upstreams;            //   upstream   upstreams   。
                                             /* ngx_http_upstream_srv_conf_t */
} ngx_http_upstream_main_conf_t;

그 중의 upstream 구성원 은 하나의 배열 이 고 배열 의 모든 요 소 는 ngx 이다.http_upstream_srv_conf_t 타 입의.ngx_http_upstream_srv_conf_t 정 의 는 다음 과 같다.
struct ngx_http_upstream_srv_conf_s {
    ngx_http_upstream_peer_t         peer;
    void                           **srv_conf;

    ngx_array_t                     *servers;  /* ngx_http_upstream_server_t */

    ngx_uint_t                       flags;
    ngx_str_t                        host;
    u_char                          *file_name;
    ngx_uint_t                       line;
    in_port_t                        port;
    ngx_uint_t                       no_port;  /* unsigned no_port:1 */

#if (NGX_HTTP_UPSTREAM_ZONE)
    ngx_shm_zone_t                  *shm_zone;
#endif
};

그 중의 server 필드 는 이 upstream 설정 의 모든 server 에 대한 상세 한 정 보 를 저장 합 니 다. ip, weight, max 를 포함 합 니 다.conns, down 등 정보.
typedef struct {
    ngx_str_t                        name;
    ngx_addr_t                      *addrs;
    ngx_uint_t                       naddrs;
    ngx_uint_t                       weight;
    ngx_uint_t                       max_conns;
    ngx_uint_t                       max_fails;
    time_t                           fail_timeout;
    ngx_msec_t                       slow_start;
    ngx_uint_t                       down;

    unsigned                         backup:1;

    NGX_COMPAT_BEGIN(6)
    NGX_COMPAT_END
} ngx_http_upstream_server_t;

upstream 설정 을 분석 하 는 과정
명령 을 분석 하지 못 했 습 니 다. nginx 메 인 프레임 워 크 는 모든 모듈 을 옮 겨 다 니 며 commands 배열 을 확인 합 니 다. 어떤 모듈 이 이 설정 명령 에 관심 이 있 는 지 보고 해당 하 는 handler 방법 으로 처리 합 니 다."upstream" 설정 에 관심 이 있 는 모듈 은 ngx 입 니 다.http_upstream_module, 그리고 정 의 된 handler 방법 은 ngxhttp_upstream。 그럼 다음은 ngxhttp_upstream 은 어떤 일 을 했 습 니까?http_upstream_add 이 방법 은 새로 해 석 된 upstream 에 대응 하 는 ngx 를 만 듭 니 다.http_upstream_srv_conf_t 구조 체, 그리고 이 를 ngx 에 추가http_upstream_main_conf_t 의 배열 중.2 새로운 ngx 만 들 기http_conf_ctx_t 구조 체, 이 구조 체 는 nginx 시작 프로 세 스에 사용 되 며, 모든 main, srv, loc 의 설정 구조 체 를 저장 합 니 다.3 현재 설정 항목 의 ctx mainconf 는 새로운 ctx 에 직접 할당 합 니 다. upstream 설정 항목 을 분석 하 는 것 은 main 의 설정 구조 체 에 영향 을 주지 않 기 때문에 직접 할당 할 수 있 습 니 다. 이전의 main 을 지연 시 킬 수 있 습 니 다.conf。 4. cycle 의 module 배열 을 옮 겨 다 니 며 http 모듈 의 create 를 호출 합 니 다.srv_conf 와 createloc_conf 방법, 새로운 HTTP 모듈 의 설정 구조 체 를 생 성하 고, 새로운 ctx 에 추가 하 는 srcconf 와 locconf 배열 중.5 첫 번 째 단계 에서 돌아 온 것 은 ngxhttp_upstream_srv_conf_t 구조 체 는 이 upstream 의 기본 정보 만 초기 화 했 을 뿐 server 구성원 과 관련 되 지 않 았 습 니 다. 다음은 ngx 를 만 드 는 것 입 니 다.http_upstream_server_t 구조 체, 다음 에 모든 server 를 분석 하기 위해 준비 합 니 다.6. 새로운 ctx 를 오래된 cf 의 ctx 구성원 으로 교체 합 니 다.이 를 통 해 알 수 있 듯 이 매번 설정 항목 을 해석 할 때마다 ngxconf_t cf 의 ctx 구성원 들 은 최신 설정 컨 텍스트 정 보 를 저장 하기 위해 끊임없이 업데이트 합 니 다.7 호출 ngxconf_parse 함수, 계속 아래로 해석 합 니 다.
주의 4 단계: 모든 http 모듈 을 옮 겨 다 니 며, ngx 를 포함 합 니 다.http_core_module, 그리고 ngxhttp_upstream_module 자체, 그들의 create 호출srv_conf 와 createloc_conf 방법 은 해당 하 는 저장 설정 항목 의 구조 체 를 다시 만 드 는 것 입 니 다. 이 작업 은 이전에 이미 진행 되 었 습 니 다.
static char *
ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
    char *rv;
    void *mconf;
    ngx_str_t *value;
    ngx_url_t u;
    ngx_uint_t m;
    ngx_conf_t pcf;
    ngx_http_module_t *module;
    ngx_http_conf_ctx_t *ctx, *http_ctx;
    ngx_http_upstream_srv_conf_t *uscf;

    ngx_memzero(&u, sizeof(ngx_url_t));

    value = cf->args->elts;
    u.host = value[1];
    u.no_resolve = 1;
    u.no_port = 1;
    /*     upstream,     ngx_http_upstream_srv_conf_t  ,      */    
    uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE | NGX_HTTP_UPSTREAM_WEIGHT | NGX_HTTP_UPSTREAM_MAX_CONNS | NGX_HTTP_UPSTREAM_MAX_FAILS | NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | NGX_HTTP_UPSTREAM_DOWN | NGX_HTTP_UPSTREAM_BACKUP);
    if (uscf == NULL)
    {
        return NGX_CONF_ERROR;
    }

    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL)
    {
        return NGX_CONF_ERROR;
    }

    http_ctx = cf->ctx;
    ctx->main_conf = http_ctx->main_conf;

    /* the upstream{}'s srv_conf */
    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL)
    {
        return NGX_CONF_ERROR;
    }
    // ngx_http_upstream_module.ctx_index   upstream      HTTP      
    ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;

    uscf->srv_conf = ctx->srv_conf;

    /* the upstream{}'s loc_conf */

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL)
    {
        return NGX_CONF_ERROR;
    }

    for (m = 0; cf->cycle->modules[m]; m++)
    {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE)
        {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;
        //      HTTP   create_srv_conf     ctx->srv_conf  
        if (module->create_srv_conf)
        {
            mconf = module->create_srv_conf(cf);
            if (mconf == NULL)
            {
                return NGX_CONF_ERROR;
            }

            ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
        }
        //       HTTP   create_loc_conf     ctx->loc_conf  
        if (module->create_loc_conf)
        {
            mconf = module->create_loc_conf(cf);
            if (mconf == NULL)
            {
                return NGX_CONF_ERROR;
            }

            ctx->loc_conf[cf->cycle->modules[m]->ctx_index] = mconf;
        }
    }
    //        upstream  server
    uscf->servers = ngx_array_create(cf->pool, 4,
                                     sizeof(ngx_http_upstream_server_t));
    if (uscf->servers == NULL)
    {
        return NGX_CONF_ERROR;
    }

    /* parse inside upstream{} */

    pcf = *cf;
    //   ctx     cf->ctx
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_UPS_CONF;

    //         NULL, filename=NULL
    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

    if (rv != NGX_CONF_OK)
    {
        return rv;
    }

    if (uscf->servers->nelts == 0)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "no servers are inside upstream");
        return NGX_CONF_ERROR;
    }

    return rv;
}

호출 ngxhttp_upstream_add 함수 가 새로운 upstream 을 ngx 에 추가 합 니 다.http_upstream_main_conf_t 의 upstream 배열 중.ngx_http_upstream_add 는 주로 몇 가지 일 을 했 습 니 다. 1. 중복 되 는 upstream 이 있 는 지 확인 하고 있 으 면 NULL 로 돌아 가 추가 에 실 패 했 습 니 다.2 새로운 ngx 만 들 기http_upstream_srv_conf_t 구조 체 는 새로운 upstream 설정 을 저장 하고 ngx 에 추가 합 니 다.http_upstream_main_conf_t 의 upstream 배열 중.3 추가 성공 후의 ngx 를 되 돌려 줍 니 다http_upstream_srv_conf_t 구조 체.
ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
{
    ngx_uint_t i;
    ngx_http_upstream_server_t *us;
    ngx_http_upstream_srv_conf_t *uscf, **uscfp;
    ngx_http_upstream_main_conf_t *umcf;
	...
	// 1   upstream main      ,     upstreams         upstream
    umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);

    uscfp = umcf->upstreams.elts;

    for (i = 0; i < umcf->upstreams.nelts; i++)
    {
        //        upstream ,      
        if (uscfp[i]->host.len != u->host.len || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) != 0)
        {
            continue;
        }
        //      upstream,     flags    NGX_HTTP_UPSTREAM_CRTEATE
        if ((flags & NGX_HTTP_UPSTREAM_CREATE) && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE))
        {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "duplicate upstream \"%V\"", &u->host);
            return NULL;
        }

        if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port)
        {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "upstream \"%V\" may not have port %d",
                               &u->host, u->port);
            return NULL;
        }

        if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port)
        {
            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                          "upstream \"%V\" may not have port %d in %s:%ui",
                          &u->host, uscfp[i]->port,
                          uscfp[i]->file_name, uscfp[i]->line);
            return NULL;
        }

        if (uscfp[i]->port && u->port && uscfp[i]->port != u->port)
        {
            continue;
        }

        if (flags & NGX_HTTP_UPSTREAM_CREATE)
        {
            uscfp[i]->flags = flags;
            uscfp[i]->port = 0;
        }

        return uscfp[i];
    }
	// 2      ,        upstream,       ngx_http_upstream_srv_conf_t
    uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
    if (uscf == NULL)
    {
        return NULL;
    }

    uscf->flags = flags;
    uscf->host = u->host;
    uscf->file_name = cf->conf_file->file.name.data;
    uscf->line = cf->conf_file->line;
    uscf->port = u->port;
    uscf->no_port = u->no_port;

    //       upstream    
    if (u->naddrs == 1 && (u->port || u->family == AF_UNIX))
    {
        uscf->servers = ngx_array_create(cf->pool, 1,
                                         sizeof(ngx_http_upstream_server_t));
        if (uscf->servers == NULL)
        {
            return NULL;
        }

        us = ngx_array_push(uscf->servers);
        if (us == NULL)
        {
            return NULL;
        }

        ngx_memzero(us, sizeof(ngx_http_upstream_server_t));

        us->addrs = u->addrs;
        us->naddrs = 1;
    }

	//3    upstream     umcf upstream   。
    uscfp = ngx_array_push(&umcf->upstreams);
    if (uscfp == NULL)
    {
        return NULL;
    }

    *uscfp = uscf;

    return uscf;
}

좋은 웹페이지 즐겨찾기