nginx 소스 코드 분석 --- upstream 설정 분석
10741 단어 nginx
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;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
간단! Certbot을 사용하여 웹 사이트를 SSL(HTTPS)화하는 방법초보자가 인프라 주위를 정돈하는 것은 매우 어렵습니다. 이번은 사이트를 간단하게 SSL화(HTTP에서 HTTPS통신)로 변경하는 방법을 소개합니다! 이번에는 소프트웨어 시스템 Nginx CentOS7 의 환경에서 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.