Nginx的核心模块和第三方模块能够满足大部门的业务需求,如果需要添加些额外的功能,就可以使用lua内嵌到nginx实现一些业务逻辑。
安装lua
下载安装
wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz
tar zxvf LuaJIT-2.0.5.tar.gz
cd LuaJIT-2.0.5/
make install PREFIX=/www/server/nginx/LuaJIT #/www/server/nginx/LuaJIT是自定义安装路径(路径要记住)
加入环境变量
echo export LUAJIT_LIB=/www/server/nginx/LuaJIT/lib >> /etc/profile
echo export LUAJIT_INC=/www/server/nginx/LuaJIT >> /etc/profile
cat /etc/profile
source /etc/profile
查看是否安装成功
[root@VM_0_13_centos nginx]# lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
>
> print("hello world")
hello world
>
安装nginx模块
安装之前先查看nginx是否已经包含了这两个模块,使用nginx -V
,我的云服务器是新买的,已经有这两个模块了。nginx如何安装模块,参考nginx-15 第三方组件和nginx平滑升级 最近的一篇也比较详细nginx-17 动态负载均衡 这里就不重复操作了。
如果已经安装了这两个模块,下面略过。
- ngx_devel_kit
NDK(nginx development kit)模块是一个拓展nginx服务器核心功能的模块,第三方模块开发可以基于它来快速实现。 - lua-nginx-module
lua-nginx-module模块使nginx中能直接运行lua脚本
下载(可直接下载到nginx/src目录下)
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz
path是解压后的文件夹路径
--add-module=/path/lua-nginx-module-0.10.9rc7 --add-module=/path/ngx_devel_kit-0.3.0
lua
lua语法
lua实际就是一门语言,菜鸟教程
lua指令和nginx的11个阶段
ngx_lua属于nginx的一部分,它的执行指令都包含在nginx的11个步骤之中了,相应的处理阶段可以做插入式处理,即可插拔式架构,类似AOP切面编程。不过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进程不允许则只会在ini_by_lua之后调用,通常用于定时拉取配置/数据,或者后端服务的健康检查.
三、
指令:ssl_certificate_by_lua
对 https 请求的处理,即将启动下游 SSL(https)连接的 SSL 握手时执行,用例:按照每个请求设置 SSL 证书链和相应的私钥,按照 SSL 协议有选择的拒绝请求等;
四、
指令:set_by_lua、set_by_lua_file
阶段:rewrite
使用范围:server/server if、location/location if
解释:设置nginx变量,可以实现复杂的赋值逻辑;此处是阻塞的,lua代码要做到非常快。
五、
指令:write_by_lua、write_by_lua_file
阶段:rewrite tail
使用范围:http、server、location/location if
解释:rewirte阶段处理,可以实现复杂的转发/重定向逻辑。
六、
指令: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
解释:内容处理器,接收请求处理并输入相应。
八、
指令:balancer_by_lua
负载均衡
九、
指令: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-lua api 和nginx交互的api
ngx.arg 获得nginx指令参数,如跟在content_by_lua_file后面的参数
ngx.send_headers 发送响应头
ngx.print 输出响应
ngx.say 输出响应,自动添加’\n’
更多见nginx-lua api
示例
server
{
listen 80;
server_name 49.233.70.27;
index index.php index.html;
error_log /www/server/nginx/logs/error.log;
set $cachePAHT "/cache/";
location / {
content_by_lua '
--内容处理阶段
--设置响应头
ngx.header.content_type="text/html";
--读取nginx变量值,并输出
ngx.say(ngx.var.cachePAHT);
';
}
}
案例
基于商品id进行流量分发
1、获取商品id
2、获取id的哈希值,取模做负载均衡,获取到一个地址
3,利用http请求,请求到应用层服务器(nginx)
3,响应回客户端
问题:为了解决相同的内容在每台上游服务器重复的缓存
lua的http模块下载,选择releases版本下载完解压就可以
lua-resty-http
加载http模块
lua_package_path "/www/server/nginx/lua/lua-resty-http-0.15/lib/?.lua;;";
server{
...
}
lua业务逻辑脚本编写
--获取参数id
local uri_args = ngx.req.get_uri_args()
local id = uri_args["id"]
--上游服务器 这里写死了 可利用lua的http模块请求consul获取上游服务器列表
local server = {
"127.0.0.1:9503","127.0.0.1:9504"
}
--得到hash值
local hash = ngx.crc32_long(id);
--求数组的长度值
local index=(hash % table.getn(server))+1
--拼接url
url = "http://"..server[index]
--加载http包
local http=require("resty.http")
--实例化
local httpClient=http.new()
--发送http请求
local resp,err = httpClient:request_uri(url,{method="GET"})
--如果没有结果打印错误
if not resp then
ngx.say(err)
return
end
ngx.say(resp.body)
--关闭
httpClient:close()
server配置
#加载nginx-lua http模块包
lua_package_path "/www/server/nginx/lua/lua-resty-http-0.15/lib/?.lua;;";
server
{
listen 80;
server_name 49.233.70.27;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/default;
error_log /www/server/nginx/logs/error.log;#错误日志很重要
location / {
default_type text/html;
content_by_lua_file "/www/server/nginx/lua/shop.lua";
}
}
热重启nginx后,访问
可以看到,我们利用lua根据商品id,哈希取模后,转发到不同的服务器上。