openresty开发系列31--openresty执行流程
咱们先看个例子
location /test {
set $a 32;
echo $a;
set $a 56;
echo $a;
}
echo nginx第三方模块,是用于作响应输出
输出了 56
Nginx 处理每个用户请求时,都是按照若干个不一样阶段依次处理的。而不是根据配置文件上的顺序。
之上的例子 涉及到了 两个阶段 rewrite和content阶段
set属于rewrite阶段
echo属于content阶段
并且 rewrite阶段的指令 在 content阶段指令 以前执行。
实际的执行顺序应当是
set $a 32;
set $a 56;
echo $a;
echo $a;
因此输出 56
在咱们配置文件中执行的指令,能够理解为对咱们的执行阶段进行入栈
Nginx处理请求的过程一共划分为11个阶段,按照执行顺序依次是post-read、server-rewrite、
find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.
一、post-read
读取请求内容阶段,nginx读取并解析完请求头以后就当即开始运行;
例如模块 ngx_realip 就在 post-read 阶段注册了处理程序,
它的功能是迫使 Nginx 认为当前请求的来源地址是指定的某一个请求头的值。
二、server-rewrite
server请求地址重写阶段;当ngx_rewrite模块的set配置指令直接书写在server配置块中时,
基本上都是运行在server-rewrite 阶段
三、find-config
配置查找阶段,这个阶段并不支持Nginx模块注册处理程序,
而是由Nginx核心来完成当前请求与location配置块之间的配对工做。
四、rewrite
location请求地址重写阶段,当ngx_rewrite指令用于location中,就是再这个阶段运行的;
另外ngx_set_misc(设置md五、encode_base64等)模块的指令,
还有ngx_lua模块的set_by_lua指令和rewrite_by_lua指令也在此阶段。
五、post-rewrite
请求地址重写提交阶段,当nginx完成rewrite阶段所要求的内部跳转动做,若是rewrite阶段有这个要求的话;
六、preaccess
访问权限检查准备阶段,ngx_limit_req和ngx_limit_zone在这个阶段运行,
ngx_limit_req能够控制请求的访问频率,ngx_limit_zone能够控制访问的并发度;
七、access
访问权限检查阶段,标准模块ngx_access、第三方模块ngx_auth_request以及第三方模块ngx_lua的access_by_lua
指令就运行在这个阶段。配置指令可能是执行访问控制相关的任务,如检查用户的访问权限,检查用户的来源IP是否合法;
八、post-access
访问权限检查提交阶段;主要用于配合access阶段实现标准ngx_http_core模块提供的配置指令satisfy的功能。
satisfy all(与关系),satisfy any(或关系)
九、try-files
配置项try_files处理阶段;专门用于实现标准配置指令try_files的功能,
若是前 N-1 个参数所对应的文件系统对象都不存在,
try-files 阶段就会当即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的URI.
十、content
内容产生阶段,是全部请求处理阶段中最为重要的阶段,
由于这个阶段的指令一般是用来生成HTTP响应内容并输出 HTTP 响应的使命;
十一、log
日志模块处理阶段;记录日志
NGX_HTTP_POST_READ_PHASE:
#读取请求内容阶段
NGX_HTTP_SERVER_REWRITE_PHASE:
#Server请求地址重写阶段
NGX_HTTP_FIND_CONFIG_PHASE:
#配置查找阶段:
NGX_HTTP_REWRITE_PHASE:
#Location请求地址重写阶段,经常使用
NGX_HTTP_POST_REWRITE_PHASE:
#请求地址重写提交阶段
NGX_HTTP_PREACCESS_PHASE:
#访问权限检查准备阶段
NGX_HTTP_ACCESS_PHASE:
#访问权限检查阶段,经常使用
NGX_HTTP_POST_ACCESS_PHASE:
#访问权限检查提交阶段
NGX_HTTP_TRY_FILES_PHASE:
#配置项try_files处理阶段
NGX_HTTP_CONTENT_PHASE:
#内容产生阶段 最经常使用
NGX_HTTP_LOG_PHASE:
#日志模块处理阶段 经常使用
到此,应该明白Nginx 的conf中指令的书写顺序和执行顺序是两码事,切记。
有些阶段是支持 Nginx 模块注册处理程序,有些阶段并不能够。
最经常使用的是 rewrite阶段,access阶段 以及 content阶段;
不支持 Nginx 模块注册处理程序的阶段 find-config, post-rewrite, post-access,
主要是 Nginx 核心完成本身的一些逻辑。
Nginx下Lua处理阶段与使用范围
openresty发起一个请求时,会有相应的执行流程
如图
从图中可知,OpenResty 处理请求大体分为四个阶段:
1)初始化阶段(Initialization Phase)
2)重写与访问阶段(Rewrite / Access Phase)
3)内容生成阶段(Content Phase)
4)日志记录阶段(Log Phase)
咱们OpenResty作个测试,示例代码以下:
init_by_lua 'ngx.log(ngx.ERR, "init_by_lua")';
init_worker_by_lua 'ngx.log(ngx.ERR, "init_worker_by_lua")';
server {
listen 80;
location /exec {
rewrite_by_lua 'ngx.log(ngx.ERR, "rewrite_by_lua")';
set_by_lua $a 'ngx.log(ngx.ERR, "set_by_lua")';
access_by_lua 'ngx.log(ngx.ERR, "access_by_lua")';
header_filter_by_lua 'ngx.log(ngx.ERR, "header_filter_by_lua")';
body_filter_by_lua 'ngx.log(ngx.ERR, "body_filter_by_lua")';
log_by_lua 'ngx.log(ngx.ERR, "log_by_lua")';
content_by_lua 'ngx.log(ngx.ERR, "content_by_lua")';
}
}
这几个阶段的存在,应该是openresty不一样于其余多数Web server编程的最明显特征了。
因为nginx把一个会话分红了不少阶段,这样第三方模块就能够根据本身行为,挂载到不一样阶段进行处理达到目的。
这样咱们就能够根据咱们的须要,在不一样的阶段直接完成大部分典型处理了。
指令能够在http、server、server if、location、location if几个范围进行配置:
指令 所到处理阶段 使用范围 解释
init_by_lua
init_by_lua_file loading-config http
nginx Master进程加载配置时执行;一般用于初始化全局配置/预加载Lua模块
init_worker_by_lua
init_worker_by_lua_file starting-worker http
每一个Nginx Worker进程启动时调用的计时器,若是Master进程不容许则只会在init_by_lua以后调用;
一般用于定时拉取配置/数据,或者后端服务的健康检查
set_by_lua
set_by_lua_file rewrite server,server if,location,location if
设置nginx变量,能够实现复杂的赋值逻辑;此处是阻塞的,Lua代码要作到很是快;
rewrite_by_lua
rewrite_by_lua_file rewrite tail http,server,location,location if
rrewrite阶段处理,能够实现复杂的转发/重定向逻辑;
access_by_lua
access_by_lua_file access tail http,server,location,location if
请求访问阶段处理,用于访问控制
content_by_lua
content_by_lua_file content location,location if
内容处理器,接收请求处理并输出响应
header_filter_by_lua
header_filter_by_lua_file output-header-filter http,server,location,location if
响应 HTTP过滤处理(例如添加头部信息),设置header和cookie
body_filter_by_lua
body_filter_by_lua_file output-body-filter http,server,location,location if
响应 BODY过滤处理(例如完成应答内容统一成大写) 对响应数据进行过滤,好比截断、替换。
log_by_lua
log_by_lua_file log http,server,location,location if
响应完成后本地异步完成日志记录(日志能够记录在本地,还能够同步到其余机器)
阶段处理,好比记录访问量/统计平均响应时间
实际上咱们只使用其中一个阶段content_by_lua,也能够完成全部的处理。但这样作,
会让咱们的代码比较臃肿,越到后期愈加难以维护。把咱们的逻辑放在不一样阶段,分工明确,代码独立nginx