nginx 변수 다시 이야기 하기 (1)
ngx_http_script_copile 함수 가 호출 되 었 습 니 다. 일반적으로 변 수 를 처리 하 는 데 사 용 됩 니 다. 특히 설정 처리 단계 에서 변수 가 나타 날 때 (즉 "$" 로 시작 하 는 설정) 보통 이 함수 로 처리 합 니 다. 이른바 "실행 시 프로세서" 를 생 성 합 니 다."함수 의 시작 에 ngx http script init arrays 함수 가 있 습 니 다. 말 그대로 우리 도 그 역할 을 대체적으로 알 수 있 습 니 다. 여 기 는 잠시 두 었 다가 나중에 토론 하 겠 습 니 다."
핵심 적 인 처 리 는 for 순환 에 있 습 니 다. 그 중에서 sc 는 우리 가 필요 로 하 는 대부분의 정 보 를 포함 하고 있 습 니 다. 그러면 이 sc 는 도대체 어떤 내력 입 니까? 우 리 는 proxy pass 를 예 로 들 면:
ngx_http_proxy_pass:
...
/* n proxy_pass , */
if (n) {
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
sc.cf = cf;
sc.source = url; // url proxy_pass ,
/*
* ,nginx ” “
* , , ( ),
* lengths values 。
*/
sc.lengths = &plcf->proxy_lengths;
sc.values = &plcf->proxy_values;
sc.variables = n;
/* compile , lengths values , NULL 。
* : , lengths values , NULL, */
sc.complete_lengths = 1;
sc.complete_values = 1;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
다음은 ngx http script copile 의 핵심 처리 부분 을 보 겠 습 니 다.
for (i = 0; i < sc->source->len; /* void */ ) {
name.len = 0;
if (sc->source->data[i] == '$') {
// '$' , , , ( $ )
if (++i == sc->source->len) {
goto invalid_variable;
}
#if (NGX_PCRE)
{
ngx_uint_t n;
/*
* , , $ , 。
* 。
*/
if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
n = sc->source->data[i] - '0';
if (sc->captures_mask & (1 << n)) {
sc->dup_capture = 1;
}
/*
* sc->captures_mask 1, captures_mask ?
* sc 。
*/
sc->captures_mask |= 1 << n;
if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
return NGX_ERROR;
}
i++;
continue;
}
}
#endif
/*
* , , proxy_pass $host$uritest,
* nginx ,host uri, $uritest ,
* , uritest , 。
* ?nginx "{}" , ,
* ${uri}test, ,
* 。
*/
if (sc->source->data[i] == '{') {
bracket = 1;
if (++i == sc->source->len) {
goto invalid_variable;
}
// name
name.data = &sc->source->data[i];
} else {
bracket = 0;
name.data = &sc->source->data[i];
}
for ( /* void */ ; i < sc->source->len; i++, name.len++) {
ch = sc->source->data[i];
// "{}" ( break ),
if (ch == '}' && bracket) {
i++;
bracket = 0;
break;
}
/*
* , , 。
* ,
*/
if ((ch >= 'A' && ch <= 'Z')
|| (ch >= 'a' && ch <= 'z')
|| (ch >= '0' && ch <= '9')
|| ch == '_')
{
continue;
}
break;
}
if (bracket) {
ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
"the closing bracket in \"%V\" "
"variable is missing", &name);
return NGX_ERROR;
}
if (name.len == 0) {
goto invalid_variable;
}
//
sc->variables++;
// ,
if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
return NGX_ERROR;
}
continue;
}
/*
* , , , ” “
* , 。 , '?'
* ngx_http_script_add_args_code 。
*/
if (sc->source->data[i] == '?' && sc->compile_args) {
sc->args = 1;
sc->compile_args = 0;
if (ngx_http_script_add_args_code(sc) != NGX_OK) {
return NGX_ERROR;
}
i++;
continue;
}
// name ” “
name.data = &sc->source->data[i];
//
while (i < sc->source->len) {
// '$'
if (sc->source->data[i] == '$') {
break;
}
/*
* '?', ,
* sc->compile_args = 0, 。 ,
* '?' , , 。*/
if (sc->source->data[i] == '?') {
sc->args = 1;
if (sc->compile_args) {
break;
}
}
i++;
name.len++;
}
// ,sc->size ( sc->source) ,
sc->size += name.len;
//
if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
!= NGX_OK)
{
return NGX_ERROR;
}
}
// compile , 。
return ngx_http_script_done(sc);
위 에서 우 리 는 copile 과정의 주요 작업 을 분 석 했 습 니 다. 분명 세부 사항 은 논의 되 지 않 았 습 니 다. copile 과정 에서 모두 4 가지 유형 을 처리 해 야 합 니 다. $1 과 같은 capture 변수, 일반적인 변수 ($uri), args 변수, 상수 (즉 상수 문자열)사실 이러한 변수의 처리 과정 은 전체적으로 그다지 번 거 로 운 것 이 아니 라 세부 적 인 부분 은 확실히 어 려 운 것 입 니 다. 우 리 는 여기 서 정리 한 결과, 이전의 블 로 그 는 변수 와 스 크 립 트 엔진 체제 에 대해 연 구 를 한 적 이 있 습 니 다. 여기 서 이야기 한 난점 과 세부 사항 을 구입 하거나, 이전에 잘 알 지 못 했 던 분석 을 다시 한 번 검토 해 보 겠 습 니 다. 당신 과 내 가 모두 얻 을 수 있 기 를 바 랍 니 다.
절차 에 대해 일반적으로 gdb 와 함께 debug 로 그 를 맞 추 면 대체적으로 정리 할 수 있 습 니 다. 어 려 운 점 은 바로 일부 구조 중의 구성원 에 있 습 니 다. 특히 일부 태그 비트 의 사용 은 전체 시스템 을 관통 시 키 는 것 입 니 다. 이해 에 있어 많은 어려움 이 있 습 니 다. 이것 은 우리 가 여기 서 토론 하 는 중심 입 니 다. 이런 부분 에 대해 알 게 되면 절 차 는 큰 문제 가 아 닙 니 다.
먼저 ngx http script copile t 구 조 를 보 세 요. 이 구 조 는 copile 에서 사 용 된 적 이 있 습 니 다.
typedef struct {
ngx_conf_t *cf; //
ngx_str_t *source; // compile
/*
* index, ,
*/
ngx_array_t **flushes;
ngx_array_t **lengths; //
ngx_array_t **values; //
ngx_uint_t variables; // , (args ,$n )
/*
* , pcre ,
*/
ngx_uint_t ncaptures; // , $n , $3, ncaptures 3
/*
* $1,$2...$9 , 1 , dup_capture ,
* mask , $n 。
*/
ngx_uint_t captures_mask;
/*
* rewrite , ngx_http_rewrite ,
* if (sc.variables == 0 && !sc.dup_capture) {
* regex->lengths = NULL;
* }
* $n, regex->lengths NULL, ,
* ngx_http_script_regex_start_code regex->lengths , ,
* $n , captures $n, ,
* pcre captures , handler 。
*/
unsigned dup_capture:1;
ngx_uint_t size; // compile ,” “
/*
* main , 。main
* ngx_http_script_regex_code_t , main ?
* 。
*/
void *main;
unsigned compile_args:1; //
unsigned complete_lengths:1; // lengths , NULL
unsigned complete_values:1; // values
unsigned zero:1; // values , '\0'
unsigned conf_prefix:1; // ,
unsigned root_prefix:1; // conf_prefix
unsigned args:1; // compile '?'
} ngx_http_script_compile_t;
함수 ngx http script add var code 에 서 는 ngx http core main conf t (뒤에 cmcf 로 대체) 의 variables, 즉 전역 변수 배열 을 사 용 했 습 니 다.
cmcf 이기 때문에 모든 server 블록, location 블록, upstream 블록 을 포함 하여 모두 볼 수 있 습 니 다. 즉, 한 측 이 수정 하면 다른 곳 에서 변화 하 는 이 치 를 나 타 낼 수 있 습 니 다.
각 모듈 의 preconfiguration 함수 에 서 는 이 모듈 이 미리 설정 한 전역 변 수 를 cmcf - > variables keys 에 넣 습 니 다. 또 다른 중요 한 구성원 은?
cmcf - > variables, 앞에서 언급 한 cmcf - > variables keys 는 모든 미리 설 정 된 변수 (set 명령 을 통 해 설 정 된 것) 입 니 다.한편, cmcf - > variables 는 설정 에 실제 사용 되 는 변수 입 니 다. cmcf - > variables 에 있 는 변 수 는 실제 적 으로 하나의 위 치 를 차지 합 니 다. 이 변수의 더 많은 정 보 는 cmcf - > variables keys 에서 유래 되 었 기 때문에 설정 분석 이 끝 난 후에 ngx http variables init vars 함 수 를 통 해 이 변수의 중요 한 정 보 를 채 웁 니 다.
r 에 도 variables 멤버 가 있 습 니 다. 이것 은 배열 이 고 배열 구성원 의 개 수 는 cmcf - > variabels 와 같 습 니 다. cmcf - > variabels 의 멤버 유형 은 다음 과 같 습 니 다.
struct ngx_http_variable_s {
ngx_str_t name; /* */
ngx_http_set_variable_pt set_handler; /* request */
ngx_http_get_variable_pt get_handler; /* request ( uri,args ) ,r->variables */
uintptr_t data; /* set get , r request offset */
ngx_uint_t flags; /* set get , */
ngx_uint_t index; /* r->variabels cmcf->variabels */
};
r - > variables 의 멤버 유형 은:
typedef struct {
unsigned len:28; /* */
unsigned valid:1; /* */
unsigned no_cacheable:1; /* , , , ,
* , no_cacheable , , get_handler
* ,
*/
unsigned not_found:1; /* , get */
unsigned escape:1; /* */
u_char *data; /* */
} ngx_variable_value_t;
이 두 구조의 관 계 는 매우 밀접 하 다. 하 나 는 변수, 하 나 는 변수 값 이다. 그래서 nginx 는 변수 에 설 치 된 이 처리 체 제 는 예 정 된 방정식, 유사 한 연산 과정 처럼 서로 다른 변수 값 으로 운행 하여 우리 가 원 하 는 서로 다른 결 과 를 얻 을 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.