nginx 如何处理请求系列4-phase handler

server_name 匹配成功后请求进入具体的server块进行后续处理。

从nginx的内部来看,一个HTTP Request的处理过程涉及到以下几个阶段。

  • 初始化HTTP Request(读取来自客户端的数据,生成HTTP Request对象,该对象含有该请求所有的信息)。
  • 处理请求头。
  • 处理请求体。
  • 如果有的话,调用与此请求(URL或者Location)关联的handler。
  • 依次调用各phase handler进行处理。

nginx自身phase handler

phase功能

处理阶段PHASE 是否可自定义handler

  • NGX_HTTP_POST_READ_PHASE
  • NGX_HTTP_SERVER_REWRITE_PHASE
  • NGX_HTTP_FIND_CONFIG_PHASE
  • NGX_HTTP_REWRITE_PHASE
  • NGX_HTTP_POST_REWRITE_PHASE
  • NGX_HTTP_PREACCESS_PHASE
  • NGX_HTTP_ACCESS_PHASE
  • NGX_HTTP_POST_ACCESS_PHASE
  • NGX_HTTP_TRY_FILES_PHASE
  • NGX_HTTP_CONTENT_PHASE
  • NGX_HTTP_LOG_PHASE

是否可自定义handler决定了第三方模块是否能在该阶段注册程序。比如openresty就在SERVER_REWRITE_PHASE,REWRITE_PHASE, ACCESS_PHASE等阶段注册了程序代码。

分析

2018/01/15 17:20:29 [debug] 16754#16754: epoll: fd:6 ev:0001 d:00007F7F2F262F80
2018/01/15 17:20:29 [debug] 16754#16754: accept on 0.0.0.0:80, ready: 0
2018/01/15 17:20:29 [debug] 16754#16754: posix_memalign: 00007F7F2F237CA0:512 [@16](https://my.oschina.net/u/2771800)
2018/01/15 17:20:29 [debug] 16754#16754: *3 accept: 172.19.23.208:47183 fd:3
2018/01/15 17:20:29 [debug] 16754#16754: *3 event timer add: 3: 60000:1516008089821
2018/01/15 17:20:29 [debug] 16754#16754: *3 reusable connection: 1
2018/01/15 17:20:29 [debug] 16754#16754: *3 epoll add event: fd:3 op:1 ev:80002001
2018/01/15 17:20:29 [debug] 16754#16754: timer delta: 1046616
2018/01/15 17:20:29 [debug] 16754#16754: worker cycle
2018/01/15 17:20:29 [debug] 16754#16754: epoll timer: 60000
2018/01/15 17:20:29 [debug] 16754#16754: epoll: fd:3 ev:0001 d:00007F7F2F263250
2018/01/15 17:20:29 [debug] 16754#16754: *3 http wait request handler
2018/01/15 17:20:29 [debug] 16754#16754: *3 malloc: 00007F7F2F2527D0:1024
2018/01/15 17:20:29 [debug] 16754#16754: *3 recv: eof:0, avail:1
2018/01/15 17:20:29 [debug] 16754#16754: *3 recv: fd:3 178 of 1024
2018/01/15 17:20:29 [debug] 16754#16754: *3 reusable connection: 0
2018/01/15 17:20:29 [debug] 16754#16754: *3 posix_memalign: 00007F7F2F2488C0:4096 [@16](https://my.oschina.net/u/2771800)
初始化http请求申请内存,生成请求对象。

2018/01/15 17:20:29 [debug] 16754#16754: *3 http process request line
2018/01/15 17:20:29 [debug] 16754#16754: *3 http request line: "GET / HTTP/1.1"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http uri: "/"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http args: ""
2018/01/15 17:20:29 [debug] 16754#16754: *3 http exten: ""
2018/01/15 17:20:29 [debug] 16754#16754: *3 http process request header line
2018/01/15 17:20:29 [debug] 16754#16754: *3 http header: "User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http header: "Host: 172.19.23.208"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http header: "Accept: */*"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http header done
处理请求头post_read_phase阶段(ngx_http_process_request_line)


2018/01/15 17:20:29 [debug] 16754#16754: *3 event timer del: 3: 1516008089821
2018/01/15 17:20:29 [debug] 16754#16754: *3 generic phase: 0
(ngx_http_core_generic_phase)

2018/01/15 17:20:29 [debug] 16754#16754: *3 rewrite phase: 1
NGX_HTTP_SERVER_REWRITE_PHASE	

2018/01/15 17:20:29 [debug] 16754#16754: *3 using configuration ""
2018/01/15 17:20:29 [debug] 16754#16754: *3 http cl:-1 max:1048576
NGX_HTTP_FIND_CONFIG_PHASE	

2018/01/15 17:20:29 [debug] 16754#16754: *3 rewrite phase: 3
NGX_HTTP_REWRITE_PHASE

2018/01/15 17:20:29 [debug] 16754#16754: *3 post rewrite phase: 4
NGX_HTTP_POST_REWRITE_PHASE

2018/01/15 17:20:29 [debug] 16754#16754: *3 generic phase: 5
2018/01/15 17:20:29 [debug] 16754#16754: *3 generic phase: 6
2018/01/15 17:20:29 [debug] 16754#16754: *3 generic phase: 7
(ngx_http_core_generic_phase checker)

2018/01/15 17:20:29 [debug] 16754#16754: *3 access phase: 8
2018/01/15 17:20:29 [debug] 16754#16754: *3 access phase: 9
2018/01/15 17:20:29 [debug] 16754#16754: *3 access phase: 10
NGX_HTTP_ACCESS_PHASE(ngx_http_core_access_phase)

2018/01/15 17:20:29 [debug] 16754#16754: *3 post access phase: 11
NGX_HTTP_POST_ACCESS_PHASE

2018/01/15 17:20:29 [debug] 16754#16754: *3 content phase: 12
2018/01/15 17:20:29 [debug] 16754#16754: *3 content phase: 13
NGX_HTTP_CONTENT_PHASE


2018/01/15 17:20:29 [debug] 16754#16754: *3 open index "/etc/nginx/html/index.html"
2018/01/15 17:20:29 [debug] 16754#16754: *3 stat() "/etc/nginx/html/index.html" failed (2: No such file or directory)
2018/01/15 17:20:29 [debug] 16754#16754: *3 http index check dir: "/etc/nginx/html"
2018/01/15 17:20:29 [error] 16754#16754: *3 "/etc/nginx/html/index.html" is not found (2: No such file or directory), client: 172.19.23.208, server: 172.19.23.208, request: "GET / HTTP/1.1", host: "172.19.23.208"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http finalize request: 404, "/?" a:1, c:1
2018/01/15 17:20:29 [debug] 16754#16754: *3 http special response: 404, "/?"
2018/01/15 17:20:29 [debug] 16754#16754: *3 http set discard body
2018/01/15 17:20:29 [debug] 16754#16754: *3 posix_memalign: 00007F7F2F23C9B0:4096 [@16](https://my.oschina.net/u/2771800)
2018/01/15 17:20:29 [debug] 16754#16754: *3 HTTP/1.1 404 Not Found
Server: nginx/1.12.2
Date: Mon, 15 Jan 2018 09:20:29 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

需要注意content阶段没有对应结果生成时,nginx调用内置模块ngx_index-->ngx_autoindex-->ngx_static来处理。 前两个处理以/结尾的,ngx_static不处理/结尾的。当然这里可能只包含部分的debug日志。当有content生成时,后续也会有filter日志;调用了系统文件时会有http static fd:日志输出等等

这里是最简单的请求流程,且都是nginx自身模块。当配置文件中使用rewrite,index,try_files等此类能发生内部跳转的指令时nginx可以停止当前处理阶段然后跳转至特定的处理阶段。此外我们还一定要有配置指令总是依照这11个阶段顺序执行的概念。

建议

当我们在书写nginx配置文件时,尽量理解书写的配置指令运行在哪一个阶段,且在书写时按照配置指令执行顺序来书写。 当使用第三方模块时,注意其提供的配置指令的运行阶段和使用阶段。当发生"内部跳转"时,梳理请求的变化,如果有疑问,一定要通过debug日志来确定nginx指令的执行阶段,以及发生跳转后,运行阶段重新从哪个阶段(并不是所有重写都跳转至find_config阶段)开始,是否会有配置指令的多次执行。尽量小的书写配置指令,能只在location块,绝不写在server块,这样避免执行阶段引发配置指令执行污染。

参考链接

猜你喜欢

转载自my.oschina.net/monkeyzhu/blog/1649583
今日推荐