最先将 Nginx,Lua 组合到一起的是 OpenResty,它有一个 ngx_lua 模块,将 Lua 嵌入到了 Nginx 里面;随后Tengine 也包含了 ngx_lua 模块。
至于二者的区别:OpenResty 是 Nginx 的 Bundle;而 Tengine 则是 Nginx 的 Fork。值得一提的是,OpenResty 和 Tengine 均是国人自己创建的项目。
Lua 是一个简洁、轻量、可扩展的脚本语言,也是号称性能最高的脚本语言,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark 的脚本,当你把他的源码下下来编译后,你会发现解释器居然不到 200k,非常变态。很多应用程序使用 Lua 作为自己的嵌入式脚本语言,以此来实现可配置性、可扩展性。
Lua 原生支持的数据类型非常之少,它只提供了 nil、数字(缺省是双精度浮点数,可配置)、布尔量、字符串、表、子程序、协程(coroutine)以及用户自定义数据这 8 种。但是其处理表和字符串的效率非常之高,加上元表的支持,开发者可以高效的模拟出需要的复杂数据类型(比如集合、数组等)。Lua 是一个动态弱类型语言,支持增量式垃圾收集策略。有内建的,与操作系统无关的协作式多线程(coroutine)支持。它还可以用于嵌入式硬件,不仅可以嵌入其他编程语言,而且可以嵌入微处理器中。
ngx_lua 属于 nginx 的一部分,相应的处理阶段可以做插入式处理,即可插拔式架构,不过 ngx_lua 并不是所有阶段都会运行的;另外指令可以在 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 | 设置header和cookie |
body_filter_by_lua body_filter_by_lua_file | output-body-filter | http,server,location,location if | 对响应数据进行过滤,比如截断、替换。 |
log_by_lua log_by_lua_file | log | http,server,location,location if | log阶段处理,比如记录访问量/统计平均响应时间 |
先安装 Nginx 需要的一些类库:
yum install gcc yum install gcc-c++
注:此步骤只是在你的系统没有安装 gcc/gcc-c++ 的情况下才需要自行编译安装。
编译安装库 LuaJit-2.0.3:
./configure --prefix=/usr/local/luajit make PREFIX=/usr/local/luajit make install PREFIX=/usr/local/luajit
在 /etc/profile 文件中增加环境变量,并执行 source /etc/profile 使之生效(非必须):
export LUAJIT_LIB=/usr/install/luajit/lib
export LUAJIT_INC=/usr/install/luajit/include/luajit-2.0
注:此步骤只是在你的系统没有安装 LuaJIT 的情况下才需要自行编译安装。
下载模块依赖 pcre-8.34、zlib-1.2.8、ngx_devel_kit 和 lua-nginx-module,最后编译 Nginx。
Nginx配置Lua案例
worker_processes 2;
#error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 20;
}
http {
server {
listen 80;
set $idTest "idTest_11111111111" ;
log_format tracklog '$idTest $msec $remote_addr - $remote_user [$time_local] $request '
'"$status" $body_bytes_sent --"$ref1"-- '
'"$http_user_agent"';
log_format LogFormatv1 '$idTest@$msec@$remote_addr@-@$remote_user@[$time_local]@$request@'
'"$status"@$body_bytes_sent@"$http_referer"@'
'"$http_user_agent"';
access_log on;
location ~ /lua/(.*) {
default_type "text/html";
set $ref1 "Hello,Nginx & Lua !";
#设置nginx变量
set $a $1;
set $b $host;
content_by_lua '
--nginx变量
local var = ngx.var
ngx.say("ngx.var.a : ", var.a, "<br/>")
ngx.say("ngx.var.b : ", var.b, "<br/>")
ngx.say("ngx.var[2] : ", var[2], "<br/>")
ngx.var.b = 2;
ngx.say("<br/>")
--请求头
ngx.say(ngx.var.httpRef, "<br/>")
local headers = ngx.req.get_headers()
for k,v in pairs(headers) do
if type(v) == "table" then
ngx.say(k, " : ", table.concat(v, ","), "<br/>")
else
ngx.say(k, " : ", v, "<br/>")
end
end
ngx.say("------------headers end-----------", "<br/><br/><br/>")
--get请求uri参数
ngx.say("uri args begin", "<br/>")
local uri_args = ngx.req.get_uri_args()
for k, v in pairs(uri_args) do
if type(v) == "table" then
ngx.say(k, " : ", table.concat(v, ", "), "<br/>")
else
ngx.say(k, ": ", v, "<br/>")
end
end
ngx.say("uri args end", "<br/>")
ngx.say("a: ",ngx.var.arg_a, "<br/>")
ngx.say("b: ",ngx.var.arg_b, "<br/>")
--未经解码的请求 uri
local request_uri = headers["Host"] .. "/" .. ngx.var.request_uri;
ngx.say("request_uri : ", request_uri, "<br/>");
--解码后的 uri
local decode_request_uri = headers["Host"] .. "/" .. ngx.unescape_uri(ngx.var.request_uri);
ngx.var.ref1 = decode_request_uri;
ngx.say("decode request_uri : ", decode_request_uri, "<br/>");
--MD5
ngx.say("ngx.md5 : ", ngx.md5("123"), "<br/>")
--http time
ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "<br/>")
--ngx.var.http_referer = "*********************"
';
access_log /var/log/nginx/ooxx.com.access.log tracklog;
}
}
}
Nginx lua总结
最先将 Nginx,Lua 组合到一起的是 OpenResty,它有一个 ngx_lua 模块,将 Lua 嵌入到了 Nginx 里面;随后Tengine 也包含了 ngx_lua 模块。