Lua集成Redis及Nginx


http://www.lua.org/
Lua脚本的作用:嵌入到应用程序中,给应用程序提供扩展功能。

https://www.lua.org/manual/5.4/
运行方法
可以编写xxx.lu脚本,通过lua xxx.lua 运行,或者通过 lua -i 交互式编程
helloworld

[root@q101 lua_script]# vi helloworld.lua
[root@q101 lua_script]# lua helloworld.lua 
hello!

注释
单行:两个减号

--

多行注释

--[[
多行注释
多行注释
--]]

变量
全局变量:默认情况下,定义一个变量都是全局变量;
局部变量:局部变量声明时使用local关键字,例如:

--全局变量
a=1
--局部变量
local b=2

如果变量没有初始化,则默认值为nil这和Java中的null不同,例如

[root@q101 ~]# lua -i
Lua 5.4.4  Copyright (C) 1994-2022 Lua.org, PUC-Rio
> name="hello"
> local address="beijin"
> print(name)
hello
> print(address)
nil
>

数据类型
Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。 Lua 中有 8 个基本类型分别为:nilbooleannumberstringuserdatafunctionthreadtable

数据类型 描述
nil 只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean 包含两个值:false和true。nil和false是 false
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字 符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用 来创建一个空表。

lua中可以通过type函数查看对象类型,例如

> print(type("hello"))
string
> print(type(10.4))
number
> print(type(print))
function
> print(type(type))
function
> print(type(true))
boolean
> print(type(nil))
nil

https://github.com/openresty/redis2-nginx-module
openresty自带redis2-nginx-module,可以直接使用
Nginx配置

location = /foo {
     default_type text/html;
     redis2_query set k1 'aaa';
     # 请求转发Redis
     redis2_pass 127.0.0.1:6379;
}

重启后访问http://192.168.88.101/foo,查看Redis中k1值

get请求

# 访问 ip/get?key=xxx
location = /get {
     default_type text/html;
     redis2_pass 127.0.0.1:6379;
     #redis2_query auth 123123;
     set_unescape_uri $key $arg_key;  # this requires ngx_set_misc
     redis2_query get $key;
}

set请求

location = /set {
    default_type text/html;
    redis2_pass 127.0.0.1:6379;
    #redis2_query auth 123123;
     # $arg_xxx未自定义
     set_unescape_uri $key $arg_uid;  # this requires ngx_set_misc
     set_unescape_uri $val $arg_uname;  # this requires ngx_set_misc
     redis2_query set $key $val;
 }

请求http://192.168.88.101/set?uid=11111&uname=zhangsan,查看Redis

操作集群

upstream redis_cluster {
     server 192.168.88.101:6379;
     server 192.168.88.102:6379;
 }
location = /redis {
default_type text/html;
         redis2_next_upstream error timeout invalid_response;
         redis2_query get foo;
         redis2_pass redis_cluster;
}

其他更多方法,参考官方文档。通过redis2-nginx-module需要对Nginx配置进行修改,不适用于复杂场景。通常使用更多的是通过外置lua脚本编写业务逻辑,Nginx conf引用lua,比如lua-resty-redis。

http://192.168.88.101/luaresty

更多使用参考:https://github.com/openresty/lua-resty-redis
redis-cluster支持
参考:https://github.com/steve0511/resty-redis-cluster

http://openresty.org/cn/linux-packages.html

yum install yum-utils
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
yum install openresty -y
yum install openresty-resty -y

启动\关闭\重启等命令

# 启动
systemctl start openresty
# 查看状态
systemctl status openresty
# 加载配置
systemctl reload openresty
# 关闭
systemctl stop openresty

查看版本openresty -v

[root@q101 utils]# openresty -v
nginx version: openresty/1.19.9.1

测试lua脚本

vi /usr/local/openresty/nginx/conf/nginx.conf

# 在nginx.conf server中写入
location /lua {

    default_type text/html;
    content_by_lua 'ngx.say("

Hello, OpenResty!

")'; } # 保存后重新加载配置 systemctl reload openresty

浏览器访问http://192.168.88.101/lua

获取请求nginx uri中的变量
nginx配置修改

location /nginx_var {
      default_type text/html;
      content_by_lua_block {
         # arg_a表示获取参数名为a的参数值
         ngx.say(ngx.var.arg_a)
     }
 }

重新加载配置后浏览器访问:http://192.168.88.101/nginx_var?a=123123

https://github.com/ledgetech/lua-resty-http
下载后将lua-resty-http/lib/resty下所有文件上传到/usr/local/openresty/lualib/resty

编写脚本
vi /usr/local/openresty/nginx/script/resty1.lua
内容如下

local http = require("resty.http")
local httpc = http.new()

--http://www.baidu.com/s?wd=test
local resp, err = httpc:request_uri("http://www.baidu.com", {
    method = "GET",
    path = "/s?wd=test",
    headers = {
        ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"
    }
})

if not resp then
    ngx.say("request error :", err)
    return
end

ngx.status = resp.status

for k, v in pairs(resp.headers) do
    if k ~= "Transfer-Encoding" and k ~= "Connection" then
        ngx.header[k] = v
    end
end

ngx.say(resp.body)
httpc:close()

配置nginx

resolver 8.8.8.8;
location /resty1 {
    default_type text/html;
    content_by_lua_file script/resty1.lua;
}

测试
访问:http://192.168.88.101/resty1

http://192.168.88.101/resty2?id=1

访问:http://192.168.88.101/resty2?id=4