nginx与lua的执行顺序和步骤说明

时间:16-01-02 来源: 作者: 点击:

一、nginx执行步骤

nginx在处理每一个用户请求时,都是按照若干个不同的阶段依次处理的,与配置文件上的顺序没有关系,详细内容可以阅读《深入理解nginx:模块开发与架构解析》这本书,这里只做简单介绍;

1、post-read

读取请求内容阶段,nginx读取并解析完请求头之后就立即开始运行;

2、server-rewrite

server请求地址重写阶段;

3、find-config

配置查找阶段,用来完成当前请求与location配重块之间的配对工作;

4、rewrite

location请求地址重写阶段,当ngx_rewrite指令用于location中,就是再这个阶段运行的;

5、post-rewrite

请求地址重写提交阶段,当nginx完成rewrite阶段所要求的内部跳转动作,如果rewrite阶段有这个要求的话;

6、preaccess

访问权限检查准备阶段,ngx_limit_req和ngx_limit_zone在这个阶段运行,ngx_limit_req可以控制请求的访问频率,ngx_limit_zone可以控制访问的并发度;

7、access

权限检查阶段,ngx_access在这个阶段运行,配置指令多是执行访问控制相关的任务,如检查用户的访问权限,检查用户的来源IP是否合法;

8、post-access

访问权限检查提交阶段;

9、try-files

配置项try_files处理阶段;

10、content

内容产生阶段,是所有请求处理阶段中最为重要的阶段,因为这个阶段的指令通常是用来生成HTTP响应内容的;

11、log

日志模块处理阶段;

二、ngx_lua运行指令

ngx_lua属于nginx的一部分,它的执行指令都包含在nginx的11个步骤之中了,不过ngx_lua并不是所有阶段都会运行的;

1、init_by_lua、init_by_lua_file

语法:init_by_lua

语境:http

阶段:loading-config

当nginx master进程在加载nginx配置文件时运行指定的lua脚本,通常用来注册lua的全局变量或在服务器启动时预加载lua模块:

init_by_lua 'cjson = require "cjson"'; server { location = /api { content_by_lua ' ngx.say(cjson.encode({dog = 5, cat = 6})) ' } }

或者初始化lua_shared_dict共享数据:

lua_shared_dict dogs 1m; init_by_lua ' local dogs = ngx.shared.dogs; dogs:set("Tom", 50) ' server { location = /api { content_by_lua ' local dogs = ngx.shared.dogs; ngx.say(dogs:get("Tom")) ' } }

但是,lua_shared_dict的内容不会在nginx reload时被清除。所以如果你不想在你的init_by_lua中重新初始化共享数据,那么你需要在你的共享内存中设置一个标志位并在init_by_lua中进行检查。

因为这个阶段的lua代码是在nginx forks出任何worker进程之前运行,数据和代码的加载将享受由操作系统提供的copy-on-write的特性,从而节约了大量的内存。

不要在这个阶段初始化你的私有lua全局变量,因为使用lua全局变量会照成性能损失,并且可能导致全局命名空间被污染。

这个阶段只支持一些小的LUA Nginx API设置:ngx.log和print、ngx.shared.DICT;

2、init_worker_by_lua、init_worker_by_lua_file

语法:init_worker_by_lua

语境:http

阶段:starting-worker

在每个nginx worker进程启动时调用指定的lua代码。如果master 进程不允许,则只会在init_by_lua之后调用。

这个hook通常用来创建每个工作进程的计时器(通过lua的ngx.timer API),进行后端健康检查或者其它日常工作:

init_worker_by_lua: local delay = 3 -- in seconds local new_timer = ngx.timer.at local log = ngx.log local ERR = ngx.ERR local check check = function(premature) if not premature then -- do the health check other routine work local ok, err = new_timer(delay, check) if not ok then log(ERR, "failed to create timer: ", err) return end end end local ok, err = new_timer(delay, check) if not ok then log(ERR, "failed to create timer: ", err) end

3、set_by_lua、set_by_lua_file

语法:set_by_lua $res [$arg1 $arg2 …]

语境:server、server if、location、location if

阶段:rewrite

传入参数到指定的lua脚本代码中执行,并得到返回值到res中。中的代码可以使从ngx.arg表中取得输入参数(顺序索引从1开始)。

这个指令是为了执行短期、快速运行的代码因为运行过程中nginx的事件处理循环是处于阻塞状态的。耗费时间的代码应该被避免。

此外注意,这个指令只能一次写出一个nginx变量,但是使用ngx.var接口可以解决这个问题:

location /foo { set $diff ''; set_by_lua $num ' local a = 32 local b = 56 ngx.var.diff = a - b; --写入$diff中 return a + b; --返回到$sum中 ' echo "sum = $sum, diff = $diff"; }

声明:本文由(Nginx运维与架构)版权所有,禁止转载,文章链接:http://www.nd9p.com/17.html