1. 이벤트 이벤트와 http 프레임워크 간의 상호 작용
http 요청 라인과 http 요청 헤더를 수신한 후 ngx_http_process_request 함수가 호출되어 http 요청 처리를 시작합니다. http 요청은 11개의 처리 단계로 구성되고 각 처리 단계에서는 여러 http 모듈이 개입할 수 있으므로 이 함수에서는 각 단계의 http 모듈이 요청을 함께 완료하도록 예약됩니다.
//接收到http请求行与请求头后,http的处理流程,是第一个http处理请求的读事件回调 //这个函数执行后,将把读写事件的回调设置为ngx_http_request_handler。这样下次再有事件时 //将调用ngx_http_request_handler函数来处理,而不会再调用ngx_http_process_request了 static void ngx_http_process_request(ngx_http_request_t *r) { ngx_connection_t *c; c = r->connection; //因为已经接收完http请求行、请求头部了,准备调用各个http模块处理请求了。 //因此需要接收任何来自客户端的读事件,也就不存在接收http请求头部超时问题 if (c->read->timer_set) { ngx_del_timer(c->read); } //重新设置当前连接的读写事件回调 c->read->handler = ngx_http_request_handler; c->write->handler = ngx_http_request_handler; //设置http请求对象的读事件回调,这个回调不做任何的事情。 //那http请求对象的读事件回调,与上面的连接对应的读事件回调有什么关系呢? //当读事件发生后,连接对应的读事件回调ngx_http_request_handler会被调用, //在这个回调内会调用http请求对象的读事件回调ngx_http_block_reading,而这个回调是 //不会做任何事件的,因此相当于忽略了读事件。因为已经接收完了请求行请求头,现在要做的是调用各个http模块, //对接收到的请求行请求头进行处理 r->read_event_handler = ngx_http_block_reading; //调用各个http模块协同处理这个请求 ngx_http_handler(r); //处理子请求 ngx_http_run_posted_requests(c); }
ngx_http_process_request 함수는 한 번만 호출됩니다. 하나의 일정이 11개의 http 단계를 모두 처리할 수 없는 경우 연결 개체에 해당하는 읽기 및 쓰기 이벤트 콜백이 ngx_http_request_handler로 설정됩니다. 요청 객체의 읽기 이벤트는 ngx_http_block_reading으로 설정되고, 요청 객체의 쓰기 이벤트 콜백은 ngx_http_core_run_phases로 설정됩니다. 이 콜백은 ngx_http_handler에 설정됩니다. 이런 식으로 이벤트가 다시 발생하면
ngx_http_process_request 함수가 호출되지 않습니다. 그렇다면 이벤트 이벤트 모듈의 읽기 및 쓰기 이벤트 콜백과 http 요청 개체의 읽기 및 쓰기 이벤트 콜백 사이의 관계는 무엇입니까?
//http请求处理读与写事件的回调,在ngx_http_process_request函数中设置。 //这个函数中将会调用http请求对象的读写事件回调。将event事件模块与http框架关联起来 static void ngx_http_request_handler(ngx_event_t *ev) { //如果同时发生读写事件,则只有写事件才会触发。写事件优先级更高 if (ev->write) { r->write_event_handler(r); //在函数ngx_http_handler设置为:ngx_http_core_run_phases } else { r->read_event_handler(r); //在函数ngx_http_process_request设置为:ngx_http_block_reading } //处理子请求 ngx_http_run_posted_requests(c); }
연결 개체의 읽기 이벤트 콜백에서 확인할 수 있습니다. http 요청 객체의 읽기 이벤트 콜백이 호출됩니다. 연결 개체의 쓰기 이벤트 콜백은 http 요청 개체의 쓰기 이벤트 콜백을 호출합니다.
그림을 보면 이벤트의 읽기 이벤트가 발생하면 epoll이 반환된 후 읽기 이벤트의 콜백 ngx_http_request_handler가 호출되는 것을 알 수 있습니다. 이 읽기 이벤트 콜백에서는 http 프레임워크, 즉 http 요청 객체의 읽기 이벤트 콜백 ngx_http_block_reading이 호출됩니다. 이 http 요청 객체의 읽기 이벤트 콜백은 읽기 이벤트를 무시하는 것과 같습니다. 따라서 http 프레임은 이벤트 모듈로 반환됩니다. 그렇다면 모든 http 요청 라인과 요청 헤더가 수신되었기 때문에 왜 읽기 이벤트를 무시해야 할까요? 이제 우리가 해야 할 일은 수신된 요청 라인과 요청 헤더의 처리를 완료하기 위해 다양한 http 모듈이 함께 작동하도록 예약하는 것입니다. 따라서 클라이언트로부터 데이터를 받을 필요가 없습니다.件 件 이벤트 처리는 훨씬 더 복잡합니다. 이벤트 쓰기 이벤트가 발생하면 EPOLL이 반환된 후 요청 개체의 쓰기 이벤트 콜백 ngx_http_core_run_phases의 콜백을 호출합니다. 이 http 프레임워크의 콜백은 11개 요청 단계에 포함된 각 http 모듈의 핸들러 메서드를 예약하여 http 요청을 공동으로 완료합니다.
2. 요청을 처리하도록 http 모듈 예약
//调用各个http模块协同处理这个请求 void ngx_http_handler(ngx_http_request_t *r) { //不需要进行内部跳转。什么是内部跳转? 例如有个location结构,里面的 // if (!r->internal) { //将数组序号设为0,表示从数组第一个元素开始处理http请求 //这个下标很重要,决定了当前要处理的是11个阶段中的哪一个阶段, //以及由这个阶段的哪个http模块处理请求 r->phase_handler = 0; } else { //需要做内部跳转 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); //将序号设置为server_rewrite_index r->phase_handler = cmcf->phase_engine.server_rewrite_index; } //设置请求对象的写事件回调,这个回调将会调度介入11个http阶段的各个http模块 //共同完成对请求的处理 r->write_event_handler = ngx_http_core_run_phases; //开始调度介入11个http阶段的各个http模块 ngx_http_core_run_phases(r); }ngx_http_core_run_phases 함수는 매우 간단합니다. 11개의 http 처리 단계와 관련된 모든 http 모듈의 검사기 방법을 예약합니다.
//调用各个http模块协同处理这个请求, checker函数内部会修改phase_handler void ngx_http_core_run_phases(ngx_http_request_t *r) { cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ph = cmcf->phase_engine.handlers; //调用各个http模块的checker方法,使得各个http模块可以介入http请求 while (ph[r->phase_handler].checker) { rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]); //从http模块返回ngx_ok,http框架则会把控制全交还给事件模块 if (rc == ngx_ok) { return; } }2단계의 http 요청에 3개의 http 모듈이 관련되고, 3단계의 http 요청에 관련된 모듈이 1개, 4단계의 요청에 관련된 모듈이 하나 있다고 가정합니다. 2단계가 처리되기 시작하면 2단계의 모든 http 모듈이 호출되어 처리됩니다. 이때 Phase_handler는 2단계의 시작 위치를 가리킵니다. 2단계의 각 모듈이 처리된 후, Phase_handler는 2단계 처리가 완료될 때까지 2단계의 다음 모듈을 가리킵니다.的 2단계의 모든 HTTP 모듈이 처리되면 Phase_handler는 기간 3을 가리킵니다. 3단계에는 하나의 HTTP 모듈만 있으므로 3단계의 모든 HTTP 모듈이 처리되어 완료됩니다. 그러면 이 핸들러 배열은 언제 생성되었습니까? 각 http 모듈의 검사기 콜백은 무엇을 합니까? 다음으로 이 두 가지 질문을 분석하겠습니다.
Three , 11 http 요청 단계 배열 생성
nginx.conf 구성을 구문 분석할 때 파일에서 http 블록이 구문 분석되면 ngx_http_block 함수가 호출되어 http 블록 구문 분석을 시작합니다. 이 함수에서는 11개의 http 요청 단계에 개입해야 하는 모든 http 모듈도 배열에 등록됩니다.
//开始解析http块 static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { //http配置解析完成后的后续处理,使得各个http模块可以介入到11个http阶段 for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != ngx_http_module) { continue; } module = ngx_modules[m]->ctx; if (module->postconfiguration) { //每一个http模块的在这个postconfiguration函数中,都可以把自己注册到11个http阶段 if (module->postconfiguration(cf) != ngx_ok) { return ngx_conf_error; } } } }예를 들어, ngx_http_static_module 정적 모듈은 11개의 http 단계에 개입하는 ngx_http_content_phase 단계 콜백을 ngx_http_static_handler
로 설정합니다.
//静态模块将自己注册到11个http请求阶段中的ngx_http_content_phase阶段 static ngx_int_t ngx_http_static_init(ngx_conf_t *cf) { cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); h = ngx_array_push(&cmcf->phases[ngx_http_content_phase].handlers); //静态模块在ngx_http_content_phase阶段的处理方法 *h = ngx_http_static_handler; return ngx_ok; }
例如: ngx_http_access_module访问权限模块,会将自己介入11个http阶段的ngx_http_access_phase阶段回调设置为ngx_http_access_handler
//访问权限模块将自己注册到11个http请求阶段中的ngx_http_access_phase阶段 static ngx_int_t ngx_http_access_init(ngx_conf_t *cf) { cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); h = ngx_array_push(&cmcf->phases[ngx_http_access_phase].handlers); //访问权限模块在ngx_http_access_phase阶段的处理方法 *h = ngx_http_access_handler; return ngx_ok; }
上面的这些操作,只是把需要介入到11个http阶段的http模块保存到了ngx_http_core_main_conf_t中的phases成员中,并没有保存到phase_engine中。那什么时候将phases的内容保存到phase_engine中呢? 还是在ngx_http_block函数中完成
//开始解析http块 static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { //初始化请求的各个阶段 if (ngx_http_init_phase_handlers(cf, cmcf) != ngx_ok) { return ngx_conf_error; } }
假设阶段1有一个http模块介入请求,阶段2有三个http模块介入请求、阶段3也有一个http模块介入请求。则ngx_http_init_phase_handlers这个函数调用后,从ngx_http_phase_t phases[11]数组转换到ngx_http_phase_handler_t handlers数组的过程如下图所示:
//初始化请求的各个阶段 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) { //11个http请求阶段,每一个阶段都可以有多个http模块介入。 //这里统计11个节点一共有多个少http模块。以便下面开辟空间 for (i = 0; i < ngx_http_log_phase; i++) { n += cmcf->phases[i].handlers.nelts; } //开辟空间,存放介入11个处理阶段的所有http模块的回调 ph = ngx_pcalloc(cf->pool,n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); cmcf->phase_engine.handlers = ph; n = 0; //对于每一个http处理阶段,给该阶段中所有介入的http模块赋值 for (i = 0; i < ngx_http_log_phase; i++) { h = cmcf->phases[i].handlers.elts; switch (i) { case ngx_http_server_rewrite_phase://根据请求的uri查找location之前,修改请求的uri阶段 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) { cmcf->phase_engine.server_rewrite_index = n; //重定向模块在数组中的位置 } checker = ngx_http_core_rewrite_phase; //每一个阶段的checker回调 break; case ngx_http_find_config_phase://根据请求的uri查找location阶段(只能由http框架实现) find_config_index = n; ph->checker = ngx_http_core_find_config_phase; n++; ph++; continue; case ngx_http_rewrite_phase: //根据请求的rui查找location之后,修改请求的uri阶段 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) { cmcf->phase_engine.location_rewrite_index = n; } checker = ngx_http_core_rewrite_phase; break; case ngx_http_post_rewrite_phase: //ngx_http_rewrite_phase阶段修改rul后,防止递归修改uri导致死循环阶段 if (use_rewrite) { ph->checker = ngx_http_core_post_rewrite_phase; ph->next = find_config_index;//目的是为了地址重写后,跳转到ngx_http_find_config_phase阶段,根据 //url重写查找location n++; ph++; } continue; case ngx_http_access_phase: //是否允许访问服务器阶段 checker = ngx_http_core_access_phase; n++; break; case ngx_http_post_access_phase: //根据ngx_http_access_phase阶段的错误码,给客户端构造响应阶段 if (use_access) { ph->checker = ngx_http_core_post_access_phase; ph->next = n; ph++; } continue; case ngx_http_try_files_phase: //try_file阶段 if (cmcf->try_files) { ph->checker = ngx_http_core_try_files_phase; n++; ph++; } continue; case ngx_http_content_phase: //处理http请求内容阶段,大部分http模块最愿意介入的阶段 checker = ngx_http_core_content_phase; break; default: //ngx_http_post_read_phase, //ngx_http_preaccess_phase, //ngx_http_log_phase三个阶段的checker方法 checker = ngx_http_core_generic_phase; } n += cmcf->phases[i].handlers.nelts; //每一个阶段中所介入的所有http模块,同一个阶段中的所有http模块有唯一的checker回调, //但handler回调每一个模块自己实现 for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { ph->checker = checker; ph->handler = h[j]; ph->next = n; ph++; } } return ngx_ok; }
四、http阶段的checker回调
在11个http处理阶段中,每一个阶段都有一个checker函数,当然有些阶段的checker函数是相同的。对每一个处理阶段,介入这个阶段的所有http模块都共用同一个checker函数。这些checker函数的作用是调度介入这个阶段的所有http模块的handler方法,或者切换到一下个http请求阶段。下面分析下ngx_http_post_read_phase,ngx_http_preaccess_phase,ngx_http_log_phase三个阶段的checker方法。
//ngx_http_post_read_phase, //ngx_http_preaccess_phase, //ngx_http_log_phase三个阶段的checker方法 //返回值: ngx_ok,http框架会将控制权交还给epoll模块 ngx_int_t ngx_http_core_generic_phase(ngx_http_request_t *r,ngx_http_phase_handler_t *ph) { ngx_int_t rc; //调用http模块的处理方法,这样这个http模块就介入到了这个请求阶段 rc = ph->handler(r); //跳转到下一个http阶段执行 if (rc == ngx_ok) { r->phase_handler = ph->next; return ngx_again; } //执行本阶段的下一个http模块 if (rc == ngx_declined) { r->phase_handler++; return ngx_again; } //表示刚执行的handler无法在这一次调度中处理完这一个阶段, //需要多次调度才能完成 if (rc == ngx_again || rc == ngx_done) { return ngx_ok; } //返回出错 /* rc == ngx_error || rc == ngx_http_... */ ngx_http_finalize_request(r, rc); return ngx_ok; }
위 내용은 nginx가 http 요청을 처리하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

Nginx가 인기있는 이유는 속도, 효율성 및 제어의 장점 때문입니다. 1) 속도 : 비동기 및 비 블로킹 처리를 채택하고 동시 연결이 높으며 강력한 정적 파일 서비스 기능이 있습니다. 2) 효율성 : 메모리 사용량이 낮고 강력한로드 밸런싱 기능. 3) 제어 : 유연한 구성 파일 관리 동작을 통해 모듈 식 설계는 확장을 용이하게합니다.

커뮤니티, 지원 및 리소스 측면에서 Nginx와 Apache의 차이점은 다음과 같습니다. 1. Nginx 커뮤니티는 작지만 활발하고 전문적이며 공식 지원은 NginxPlus를 통해 고급 기능과 전문 서비스를 제공합니다. 2. Apache에는 거대하고 활발한 커뮤니티가 있으며 공식 지원은 주로 풍부한 문서 및 커뮤니티 리소스를 통해 제공됩니다.

NginXunit은 Python, PHP, Java, Go 등과 같은 다양한 프로그래밍 언어 및 프레임 워크를 지원하는 오픈 소스 응용 프로그램 서버입니다. 1. 동적 구성을 지원하고 서버를 다시 시작하지 않고 응용 프로그램 구성을 조정할 수 있습니다. 2.nginxunit은 다중 언어 응용 프로그램을 지원하여 다국어 환경의 관리를 단순화합니다. 3. 구성 파일을 사용하면 Python 및 PHP 응용 프로그램 실행과 같은 응용 프로그램을 쉽게 배포하고 관리 할 수 있습니다. 4. 또한 응용 프로그램을 관리하고 스케일링하는 데 도움이되는 라우팅 및로드 밸런싱과 같은 고급 구성을 지원합니다.

Nginx는 웹 사이트 성능과 신뢰성을 향상시킬 수 있습니다. 1. 웹 서버로서 정적 컨텐츠를 프로세스합니다. 2. 리버스 프록시 서버로서의 전달 요청; 3.로드 밸런서로 요청을 할당; 4. 캐시 서버로서 백엔드 압력을 줄입니다. NGINX는 GZIP 압축 활성화 및 연결 풀링 조정과 같은 구성 최적화를 통해 웹 사이트 성능을 크게 향상시킬 수 있습니다.

nginxserveswebcontentandactsasareverseproxy, loadbalancer, andmore.1) itefficientservesstaticcontentikehtmllandimages.2) itfunctionsAresAreSeareverseProxyAndloadbalancer, 분배 TrafficacrossServers.3) nginxenhancesperformancethroughcaching.4) Itofferssecur

NginXunit은 동적 구성 및 다국어 지원으로 응용 프로그램 배포를 단순화합니다. 1) 서버를 다시 시작하지 않고 동적 구성을 수정할 수 있습니다. 2) Python, PHP 및 Java와 같은 여러 프로그래밍 언어를 지원합니다. 3) 고 동시성 처리 성능을 향상시키기 위해 비동기 비 차단 I/O 모델을 채택하십시오.

NGINX는 처음에 C10K 문제를 해결했으며 이제로드 밸런싱, 리버스 프록시 및 API 게이트웨이를 처리하는 모든 라운드로 발전했습니다. 1) 이벤트 중심 및 비 블로킹 아키텍처에서 잘 알려져 있으며 높은 동시성에 적합합니다. 2) NGINX는 IMAP/POP3을 지원하는 HTTP 및 리버스 프록시 서버로 사용될 수 있습니다. 3) 작동 원리는 이벤트 중심 및 비동기 I/O 모델을 기반으로하며 성능을 향상시킵니다. 4) 기본 사용에는 가상 호스트 구성 및로드 밸런싱 구성이 포함되며 고급 사용량은 복잡한로드 밸런싱 및 캐싱 전략이 포함됩니다. 5) 일반적인 오류에는 구성 구문 오류 및 권한 문제가 포함되며 디버깅 기술은 Nginx-T 명령 및 stub_status 모듈 사용이 포함됩니다. 6) 성능 최적화 제안에는 작업자 매개 변수 조정, GZIP 압축 사용 및

Nginx의 일반적인 오류에 대한 진단 및 솔루션에는 다음이 포함됩니다. 1. 로그 파일보기, 2. 구성 파일 조정, 3. 성능 최적화. 로그를 분석하고 시간 초과 설정을 조정하고 캐시 및로드 밸런싱 최적화를 통해 웹 사이트 안정성 및 성능을 향상시키기 위해 404, 502, 504와 같은 오류를 효과적으로 해결할 수 있습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

드림위버 CS6
시각적 웹 개발 도구

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.