Nginx中的Lua介绍09

Nginx中的Lua操作简介

Lua

轻量小巧的脚本语言, 可以嵌入到其他应用程序中, 提供灵活的扩展定制功能

可用于游戏开发、独立应用脚本、文本应用脚本、扩展和数据库插件、系统安全上

安装lua

1
2
3
4
5
6
$ wget https://www.lua.org/ftp/lua-5.4.1.tar.gz
$ tar -zxvf lua-5.4.1.tar.gz
$ cd lua-5.4.1
$ make linux test # 测试编译环境
$ sudo make install
$ lua -v

image-20220607184810900

Lua语法

命令行运行与脚本式运行

image-20220607185129757

image-20220607185813716

1
2
#! /usr/local/bin/lua
print('hello,lua!!!')

注释

**单行注释 **

1
-- print('hello,lua!!!')

多行注释

1
2
3
4
5
--[[
print('hello,lua!!!')
print('hello,lua!!!')
print('hello,lua!!!')
--]]

取消多行注释

第一个注释符前加一个 -

1
2
3
4
5
---[[	
print('hello,lua!!!')
print('hello,lua!!!')
print('hello,lua!!!')
--]]

标识符

变量名可以使用字母数字下划线, 由于lua保留字使用下划线加大写字母, 如_VERSION , 应避免冲突

关键字

and break do else
elseif end false for
function if in local
nil not or repeat
return then true until
while goto

运算符

算术运算符 关系运算符 逻辑运算符 其他运算符
+ 加法 == 等于 and 逻辑与 && .. 字符串连接
- 减法 ~= 不等于 or 逻辑或 `
* 乘法 > 大于 not 逻辑非 !
/ 除法 < 小于
% 取余 >= 大于等于
^ 乘幂 <= 小于等于
- 负号

全局/局部变量

不声明则为全局变量, 若未提前赋值, 默认为nil, 声明局部变量, 需要使用local关键字

image-20220607200001074

数据类型

数据类型 名称 简介
nil 空, 无效值 可用于移除变量,只需要将该变量名赋值为nil
boolean 布尔 , true/false 可用于条件判断, false/nil为假, 其余均为真
number 数值 只包含两种:整型(integer)和双精度浮点型(float)
string 字符串 可用单双引号定义, 也可以使用[[ 多行文字 ]]
function 函数 使用function关键字定义, 以end结尾
table 本质为一种辅助数组, 表示数组,集合,记录等
可以使用用{}定义, 默认索引从1开始
thread 线程 用于执行协同程序
userdata 用户数据 用于表示由应用程序或C/C++语言库锁创建的类型

可以使用type()函数判断给定变量数据类型

image-20220607200553018

function定义及使用

参数可以缺省, 默认为nil, 也可以多传, 多余参数被舍弃

image-20220607202218668

也可以使用可变参数...定义传参

image-20220607202850654

控制结构-条件判断

lua中的条件判断通过if then elseif then else end 完成

1
2
3
4
5
6
7
8
-- 语法
if 条件1 then
动作1
elseif 条件2 then
动作2
else
动作3
end

image-20220607204807108

控制结构-循环语句

whil循环

1
2
3
4
-- 语法
while 条件 do
循环体
end
1
2
3
4
5
6
7
function rangePrint(n)
local i=1
while i<=n do
print(i)
i=i+1
end
end

image-20220608021530059

repeat循环

1
2
3
4
-- 语法
repeat
循环体
until 条件
1
2
3
4
5
6
7
function rangeRepeat(n)
local i=n
repeat
print(i)
i=i-1
until i<1
end

image-20220608021835989

for循环

for循环支持数值型循环和泛型循环

  • 数值型for循环

    1
    2
    3
    4
    -- 语法
    for i=start,end,step do
    循环体
    end

    i 代表当前循环数值, start代表开始数值, end代表结束数值, step代表步长

    1
    2
    3
    4
    5
    function rangeStep()
    for i=10,50,10 do
    print(i)
    end
    end

    image-20220608022903146

  • 泛型for循环

    1
    2
    3
    4
    5
    6
    7
    8
    -- 语法
    for i,v in ipairs(x) do
    循环体
    end
    -- 或
    for i,v in pairs(x) do
    循环体
    end

    ipairs不会循环非数值型元素, pairs会全部循环

    1
    2
    3
    4
    5
    function showArr(x)
    for i,v in ipairs(x) do
    print(i,v)
    end
    end

    image-20220608023932770

    image-20220608024109753

ngx_lua模块

OpenResty文档

1
2
https://www.nginx.com/resources/wiki/modules/lua/
https://github.com/openresty/lua-nginx-module

ngx_lua模块通过将lua解释器集成进Nginx, 可以采用lua脚本实现业务逻辑, 在保证高并发服务能力的同时极大的降低了实现成本

环境搭建

方式一: lua-nginx-module

1.安装LuaJIT

1
2
3
4
5
6
$ wget https://luajit.org/download/LuaJIT-2.0.5.tar.gz
$ tar -zxvf LuaJIT-2.0.5.tar.gz
$ cd LuaJIT-2.0.5
$ sudo apt install build-essential # 安装编译环境
$ make && sudo make install
$ luajit -v

2.安装lua-nginx-module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ wget https://github.com/openresty/lua-nginx-module/archive/v0.10.16rc4.tar.gz
$ tar -zxvf v0.10.16rc4.tar.gz
$ mv lua-nginx-module-0.10.16rc4 lua-nginx-module
$ export LUAJIT_LIB=/usr/local/lib
$ export LUAJIT_INC=/usr/loacl/include/luajit-2.0
$ cd lua-nginx-module
$ nginx -V # 复制结果
$ cd (nginx包路径)
$ ./configure [原有配置] --add-module=[lua-nginx-module路径]
$ sudo apt install build-essential libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev # 安装编译依赖
$ make
$ sudo mv /usr/sbin/nginx /usr/sbin/nginx.old
$ sudo mv objs/nginx /usr/sbin/nginx
$ sudo ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2 # 报错处理
$ sudo vi /etc/nginx/nginx.conf
# 报错处理 http块添加 lua_load_resty_core off;
$ sudo systemctl start nginx

3.配置lua路由,查看结果

1
2
3
4
location /lua{
default_type 'text/html';
content_by_lua 'ngx.say("<h1>hello,lua</h1>")';
}

image-20220608040828296

方式二: OpenResty

1
官网: https://openresty.org/cn/

openresty是一个基于Nginx和Lua的高性能Web平台, 内部集成了Nginx和Lua. 用于方便的搭建处理超高并发, 扩展性极强的动态Web应用服务

1
2
3
4
5
6
$ wget https://openresty.org/download/openresty-1.15.8.2.tar.gz
$ tar -zxvf openresty-1.15.8.2.tar.gz
$ cd openresty-1.15.8.2/
$ ./configure
$ make && sudo make install
$ sudo /usr/local/openresty/nginx/sbin/nginx

配置lua路由,查看结果

1
2
3
4
5
# vim /usr/local/openresty/nginx/conf/nginx.conf
location /lua{
default_type 'text/html';
content_by_lua 'ngx.say("<h1>hello,lua</h1>")';
}

image-20220608180950753

指令解析

image-20220608181255049

图中 * 作用为:

1
2
3
* : 无, 即 xxx_by_lua, 则后面应该跟的是lua指令
* :_file, 即 xxx_by_lua_file, 则后面跟的是lua文件
* :_block, 即 xxx_by_lua_block, 在0.9.17版后替代 xxx_by_lua_file

初始化阶段指令

init_by_lua*

该指令在每次Nginx重启时执行, 可以完成一些耗时模块的加载, 或初始化全局配置

init_worker_by_lua*

用于启动一些定时任务, 如心跳监测、定时拉取服务器配置等

重写/访问阶段指令

set_by_lua*

用于变量赋值, 该指令每次只能返回一个值, 并赋给指定变量名

rewrite_by_lua*

用于执行内部URL重写或外部重定向, 如伪静态化URL重写, 本阶段在rewrite处理阶段最后默认执行

access_by_lua*

用于访问控制. 如仅允许内网IP访问

ssl_certificate_by_lua*

作用在Nginx和下游服务器开始一个SSL握手操作时, 将允许执行本配置项lua代码

内容处理阶段指令

content_by_lua*

该指令是应用最多的指令, 大部分任务均在本阶段完成, 其他阶段主要是为本阶段准备数据

header_filter_by_lua*

用于设置应答消息的头信息

body_filter_by_lua*

用于对响应数据进行过滤、截断、替换操作

balancer_by_lua*

主要用于实现上游服务器的负载均衡算法

日志阶段指令

log_by_lua*

用于在log请求处理阶段, 用Lua代码处理日志, 但并不替换原有log处理

操作案例

1
2
参考文档: 
https://github.com/openresty/lua-nginx-module#nginx-api-for-lua
1
2
3
需求:
访问路径http://192.168.253.138?name=tim&gender=1
Nginx接收请求后, 根据gender传值, 若等于1,显示tim先生, 若等于0, 显示tim女士, 若即不是0也不是1, 返回tim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 配置/usr/local/openresty/nginx/conf/nginx.conf文件路由
location /getGender{
charset utf8;
default_type 'text/html';
set_by_lua $value "
-- 获取请求参数
local params = ngx.req.get_uri_args()
local name = params['name']
local gender = params['gender']
-- 判断组装返回值
if gender == '1' then
gender_str = '先生'
elseif gender == '0' then
gender_str = '女士'
else
gender_str = ''
end
str_total = name .. gender_str
-- 返回结果
return str_total
";
return 200 $value;
}
1
2
# 重启nginx
$ sudo /usr/local/openresty/nginx/sbin/nginx -s reload

image-20220608190959254