背景
了解Nginx处理HTTP请求的11个阶段,有助于理解和配置nginx、自定义模块、基于lua模块自定义功能。按如下配置,执行"curl http://localhost:8001/query/test.html",如果读者对结果不是很确定,建议阅读本文。
server {listen 8001;server_name localhost;rewrite ^/query/(.*)$ /ask/$1;location /ask {root html;try_files index.html =500;proxy_pass http://localhost:8002;rewrite ^/ask(.*)$ /query;index 50.html;return 200 "ask success";}
}
1.HTTP消息处理流程
以下分小节进行讲解Http请求进入Nginx后,处理流程按顺序分为以下11个阶段:
说明:所有阶段不是必须经历的,可能在某个阶段结束请求,如return指令后,请求就不再向下传递。
1.1 消息读取
[1] post_read
接收完完整的请求头后进入该阶段,由于未经过处理,此时保留请求的原始信息,如客户端的真实IP和原始请求路径。
说明:realip模块使用可参考:Nginx系列-10 realIp模块使用。
1.2 rewrite
[2] server_rewrite
匹配server块后进行该阶段,处理server块中的return、rewrite等指令;
说明:return和rewrite根据配置的先后顺序执行,rewrite后可以继续执行return;而return指令执行完,直接退出处理流程,直接发送响应给客户端(即配置在return后的rewrite失效)。
server {rewrite指令1;return指令;rewrite指令2;
}
此时,rewrite指令1和return指令依次执行,而rewrite指令2不会执行。
说明:rewrite指令的使用可以参考:Nginx系列-6 rewrite使用介绍
[3] find_config
根据url(被rewrite后-使用重新后的url)查找匹配的location。此阶段根据请求url和location的配置进行匹配。
说明:url匹配可以参考:Nginx系列-3 servername优先级和location优先级和常用正则表达式 和 Nginx系列-4 proxy_pass使用和路径拼接问题
[4] rewrite
进入匹配的location块后,处理location块内的return、rewrite等指令。
由此,在location中,return、rewrite指令优先级高于allow/deny, try_files, proxy_pass, index等指令。
[5] post_rewrite
判断location块内是否有重写,如果没有,进入下一阶段;如果有重写,跳到find_config阶段查询匹配的location.
此过程会判断url重写是否达到上线,如果达到上限会返回500异常,不再进行重写。
1.3 access
access包括3个阶段,用于对客户端的请求进行访问控制。
[6] pre_access
在access访问控制的前置阶段,侧重于从链路层面限制,如使用limit_req、limit_conn、limit_rate分别来控制请求数、访问速率、链接数等。
[7] access
access阶段侧重于进行业务层面的限制,如使用deny/allow实现黑白名单、使用auth模块进行用户密码校验.
说明:deny/allow的使用可以参考:Nginx系列-8 常见指令收集
[8] post_access
配合access阶段使用,如果ACCESS阶段返回了NGX_HTTP_FORBIDDEN或NGX_HTTP_UNAUTHORIZED, 会中断请求。
1.4 content
content包括2个阶段,用于生成实际的响应内容。
[9] pre_content
处理try_files指令,如果没有直接进入下一个阶段。
[10] content
处理proxy_pass、index等指令,生成响应内容。
由此可以看出,try_files的优先级高于proxy_pass和index,即当try_files和proxy_pass和index共处于location块内时,只有try_files生效。
location /ask {proxy_pass http://localhost:8002; #不生效index 50.html; #不生效try_files index.html =500; #生效
}
说明:try_files的使用可以参考Nginx系列-5 root和alias和index和try_files
1.* filter模块
对生成的content内容,进行进一步处理。
如ngx_http_sub_module模块提供的sub_filter可对生成的content进行字符替换。
filter模块不仅可以处理content阶段的响应,还可以处理return指令的结果:
server {listen 8001;server_name localhost;location /query {return 200 "8001 query success";# 将响应体中消息的success转为大写sub_filter success SUCCESS;sub_filter_types *;sub_filter_once off;}
}
测试结果如下所示:
[root@124 conf]# curl http://localhost:8001/query
8001 query SUCCESS
1.5 log
[11] log
access_log模块工作在此阶段,当请求发送给客户端后,记录访问日志,此时access.log文件中新增一条记录。
2.扩展
后续将介绍Nginx基于Lua模块扩展功能,会结合本文的http处理流程进行介绍。