nginx 소스 코드 분석 (6) - 연결 구축
이벤트 순환 에 서 는 놀 라 움 을 방지 하기 위해 서 (새로 도착 한 연결 이 모든 막 힌 worker 프로 세 스 를 깨 울 수 있 습 니 다) accept 잠 금 을 가 져 온 worker 프로 세 스 만 accept 새로운 연결 을 받 을 수 있 습 니 다. 그 다음 에 ngx 를 호출 할 수 있 습 니 다.event_accept 함수 처리.구체 적 인 과정 을 살 펴 보 겠 습 니 다.
1. ngx_event_accept
ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
ev->available = 1;
} else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {
ev->available = ecf->multi_accept;
}
이벤트 의 available 속성 을 초기 화하 여 이벤트 발생 을 표시 합 니 다. lc = ev->data;
ls = lc->listening;
ev->ready = 0;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"accept on %V, ready: %d", &ls->addr_text, ev->available);
ngx_event_t 의 data 속성 은 이 이벤트 가 있 는 연결 입 니 다. socket 의 연결 을 감청 할 때 listening 속성 을 통 해 해당 하 는 감청 socket (ngx listening t) 을 얻 을 수 있 습 니 다.다음 while 순환 은 ev - > available 횟수 를 교체 하여 해당 하 는 연결 을 가 져 오 는 데 사 용 됩 니 다.while 순환 의 시작 부분 은 accept 를 호출 하여 연결 socket 을 가 져 오 는 것 입 니 다. ngx_accept_disabled = ngx_cycle->connection_n / 8
- ngx_cycle->free_connection_n;
이벤트 모델 을 소개 할 때 ngxaccept_disabled 는 주로 워 커 프로 세 스 의 간단 한 부하 균형 을 실현 하 는 데 사 용 됩 니 다. 워 커 프로 세 스 의 남 은 연결 개수 가 연결 탱크 크기 의 1 / 8 보다 적 을 때 이 프로 세 스 는 경쟁 accept 잠 금, ngx 를 포기 합 니 다.accept_disabled 는 ngxprocess_events_and_timers 함수 에서 사용 합 니 다. c = ngx_get_connection(s, ev->log);
if (c == NULL) {
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_close_socket_n " failed");
}
return;
}
s 는 socket 을 연결 하 는 파일 설명자 입 니 다. 연결 풀 에서 연결 을 가 져 와 이 socket 에 할당 합 니 다. c->pool = ngx_create_pool(ls->pool_size, ev->log);
if (c->pool == NULL) {
ngx_close_accepted_connection(c);
return;
}
이 연결 을 위해 메모리 풀 을 만 듭 니 다. c->sockaddr = ngx_palloc(c->pool, socklen);
if (c->sockaddr == NULL) {
ngx_close_accepted_connection(c);
return;
}
ngx_memcpy(c->sockaddr, sa, socklen);
log = ngx_palloc(c->pool, sizeof(ngx_log_t));
if (log == NULL) {
ngx_close_accepted_connection(c);
return;
}
연 결 된 sockaddr 는 클 라 이언 트 socket 주 소 를 저장 합 니 다. 공간 을 할당 합 니 다.그리고 연 결 된 log 구 조 를 위해 공간 을 분배 합 니 다. if (ngx_inherited_nonblocking) {
if (ngx_event_flags & NGX_USE_AIO_EVENT) {
if (ngx_blocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_blocking_n " failed");
ngx_close_accepted_connection(c);
return;
}
}
} else {
//
if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
if (ngx_nonblocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_nonblocking_n " failed");
ngx_close_accepted_connection(c);
return;
}
}
}
aio 를 사용 할 때 차단 방식 을 사용 하고 다른 모드 (epoll, select 등) 는 비 차단 방식 을 사용 합 니 다. c->recv = ngx_recv;
c->send = ngx_send;
c->recv_chain = ngx_recv_chain;
c->send_chain = ngx_send_chain;
c->log = log;
c->pool->log = log;
c->socklen = socklen;
c->listening = ls;
c->local_sockaddr = ls->sockaddr;
c->unexpected_eof = 1;
새로운 연결 의 일부 속성 을 초기 화 합 니 다. 수신, 발송 함수, 로그, 감청 socket 등 을 포함 합 니 다.다음은 연 결 된 이벤트 부분 을 초기 화 합 니 다. rev = c->read;
wev = c->write;
wev->ready = 1;
if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
/* rtsig, aio, iocp */
rev->ready = 1;
}
if (ev->deferred_accept) {
rev->ready = 1;
#if (NGX_HAVE_KQUEUE)
rev->available = 1;
#endif
}
rev->log = log;
wev->log = log;
읽 기와 쓰기 이벤트 의 ready 속성 을 설정 합 니 다. 이 속성 은 이 이벤트 가 준비 되 었 음 을 나타 내 며 촉발 할 수 있 습 니 다. c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
ngx_connection_counter 는 nginx 의 연결 카운터 로 공유 메모리 에서 초기 화 되 는 것 을 방지 합 니 다. 이벤트 module 의 module init 리 셋 함수 에서 호출 됩 니 다. 구체 적 으로 는 ngx 입 니 다.event_module_init 함수.연 결 된 number 필드 는 이 연결 의 번 호 를 분명히 나타 낸다. if (ls->addr_ntop) {
c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len);
if (c->addr_text.data == NULL) {
ngx_close_accepted_connection(c);
return;
}
c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->addr_text.data,
ls->addr_text_max_len, 0);
if (c->addr_text.len == 0) {
ngx_close_accepted_connection(c);
return;
}
}
이 코드 는 바 이 너 리 주 소 를 텍스트 형식 으로 바 꾸 고 연 결 된 addr 에 값 을 부여 합 니 다.text 속성. if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
if (ngx_add_conn(c) == NGX_ERROR) {
ngx_close_accepted_connection(c);
return;
}
}
호출 ngxadd_conn 은 새 연결 을 nginx 의 이벤트 순환 에 추가 합 니 다.epoll 을 사용 할 때 실제로 ngx 를 호출 합 니 다.epoll_add_connection 함수, 최종 호출 epollctl 에 이 벤트 를 추가 하면 이 socket 에서 온 데 이 터 를 나중에 들 을 수 있 습 니 다. log->data = NULL;
log->handler = NULL;
/**
* socket ngx_http_init_connection(http/ngx_http_request.c), handler
* ngx_http_add_listening
*/
ls->handler(c);
ls 는 socket (ngx listening t) 을 감청 합 니 다. handler 는 accept 에서 새 연결 에 호출 되 었 습 니 다. 설명 은 이미 분명하게 말 했 습 니 다. 바로 ngx 를 호출 하 는 것 입 니 다.http_init_connection 연결 초기 화 를 마 쳤 습 니 다. 그 중에서 가장 중요 한 것 은 읽 기 이벤트 에 handler 를 설정 하 는 것 입 니 다. 다음은 이 함 수 를 보 겠 습 니 다.2. ngx_http_init_connection
ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
if (ctx == NULL) {
ngx_http_close_connection(c);
return;
}
ctx->connection = c;
ctx->request = NULL;
ctx->current_request = NULL;
c->log->connection = c->number;
c->log->handler = ngx_http_log_error;
c->log->data = ctx;
c->log->action = "reading client request line";
c->log_error = NGX_ERROR_INFO;
로그 관련 속성 을 초기 화 합 니 다. rev = c->read;
rev->handler = ngx_http_init_request;
c->write->handler = ngx_http_empty_handler;
이 코드 는 가장 핵심 적 인 것 입 니 다. 이 벤트 를 읽 는 handler 를 ngx 로 설정 합 니 다.http_init_request, 클 라 이언 트 가 서버 에 데 이 터 를 보 낼 때 호출 되 어 클 라 이언 트 요청 을 초기 화하 고 처리 합 니 다.뒤에서 ngxin 요청 처 리 를 소개 하 겠 습 니 다. 상세 하 게 소개 하 겠 습 니 다. if (rev->ready) {
/* the deferred accept(), rtsig, aio, iocp */
if (ngx_use_accept_mutex) {
ngx_post_event(rev, &ngx_posted_events);
return;
}
ngx_http_init_request(rev);
return;
}
설명 에 따 르 면 이 코드 는 deferred accept, rtsig, ao 와 iocp 를 사용 할 때 호출 되 며, ngxevent_accept 에 서 는 이 몇 가지 상황 에서 만 읽 기 이벤트 의 ready 를 1 로 설정 합 니 다. ngx_add_timer(rev, c->listening->post_accept_timeout);
/*
*
*/
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
#endif
ngx_http_close_connection(c);
return;
}
timer 를 설정 하고 마지막 으로 새 socket 설명 자 를 이벤트 순환 에 추가 합 니 다. 그러나 epoll 을 사용 할 때 이벤트 순환 에 추가 하 는 작업 은 이미 ngxadd_conn 에서 완성 되 었 기 때문에 이 함 수 는 어떠한 조작 도 하지 않 습 니 다.위 는 nginx 가 연결 을 만 드 는 처리 과정 입 니 다. 주로 연결 의 속성 을 초기 화하 고 이 벤트 를 읽 는 handler 를 설정 하여 요청 을 처리 합 니 다. 다음 편 은 nginx 의 요청 처 리 를 소개 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.