Nginx中的Lua使用10

Nging中的Lua使用

ngx_lua操作redis

1
2
3
4
5
6
7
Nginx 支持三种方法访问Redis
- HttpRedis模块
指令少, 功能单一, 适合简单缓存
- HttpRedis2Module
比较灵活, 功能强大
- lua-resty-redis库
OpenResty提供的操作Redis的接口库, 适合复杂业务逻辑

查询基本使用API

OpenResty官方文档

1
https://github.com/openresty/lua-resty-redis

在lua-resty-redis中, 所有Redis命令都有自己的方法, 名称与Redis命令相同, 只是全部小写

修改RestyNginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# sudo vi /usr/local/openresty/nginx/conf/nginx.conf
location /showRedis{
default_type 'text/html';
content_by_lua_block{
-- 引入Redis接口模块
local redis = require "resty.redis"
-- 创建Redis对象
local redisObj = redis:new()
-- 设置超时时间
redisObj:set_timeout(1000)
local ok,err = redisObj:connect("192.168.253.135",6379)
if not ok then
ngx.say('failed to connection with redis',err)
return
else
ngx.say('connect to Redis success','<br>')
end
-- 向Redis存入数据
local ok,err = redisObj:set('username','ni9ne')
if ok then
ngx.say('set value username_ni9ne:', ok,'<br>')
else
ngx.say('failed to set value',err)
return
end
-- 从Redis中获取数据
local res,err = redisObj:get('username')
ngx.say('<h1>',res,'<h1>')
-- 关闭Redis连接
redisObj:close()
}
}

验证配置路由结果

image-20220609012350518

image-20220609012412032

ngx_lua操作MySql

1
2
3
4
在ngx_lua中, MySql有两种访问方式:
- 使用OpenResty自带的ngx_lua模块和lua-resty-mysql模块
- 安装drizzle_nginx_module(HttpDrizzleModule)模块
文档路径为: https://github.com/openresty/drizzle-nginx-module

已安装OpenResty, 使用lua-resty-mysql

查询基本使用API

OpenResty官方文档

1
https://github.com/openresty/lua-resty-mysql

单条数据查询

修改Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# sudo vi /usr/local/openresty/nginx/conf/nginx.conf
location /mysqlQuery{
default_type 'text/html';
content_by_lua_block{
-- 引入resty.msyql模块
local mysql = require 'resty.mysql'
-- 创建连接对象
local db = mysql:new()
-- 建立连接
local ok,err = db:connect{
host="192.168.253.134",
port=3306,
user="root",
password="xxxxxx",
database="nginx_db"
}
-- 验证是否连接成功
if not ok then
ngx.say('failed connected to mysql',err)
return
else
ngx.say('mysql connected success'..'<br/>')
end
-- 设置超时时间
db:set_timeout(1000)
-- 发送SQL语句
db:send_query('select * from users where id=2')
-- 接收返回结果
local res,err,errcode,sqlstate = db:read_result()
-- 输出信息到页面
if not err then
ngx.say('res[1].username:',res[1].username)
ngx.say('<br/>')
end
ngx.say('err:',err)
ngx.say('<br/>')
ngx.say('errcode:',errcode)
ngx.say('<br/>')
ngx.say('sqlstate:',sqlstate)
-- 关闭连接
db:close()
}
}

验证配置路由结果

image-20220609020926699

SQL错误信息如下所示:

image-20220609021614599

多条数据查询

修改Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# sudo vi /usr/local/openresty/nginx/conf/nginx.conf
location /mysqlQuery{
default_type 'text/html';
content_by_lua_block{
local mysql = require 'resty.mysql'
local db = mysql:new()
local ok,err = db:connect{
host="192.168.253.134",
port=3306,
user="root",
password="xxxxxx",
database="nginx_db"
}
if not ok then
ngx.say('failed connected to mysql',err)
return
else
ngx.say('mysql connected success'..'<br/>')
end
db:set_timeout(1000)
db:send_query('select * from users')
local res,err,errcode,sqlstate = db:read_result()
if not err then
--[[
ngx.say('res[1].username:',res[1].username)
ngx.say('<br/>')
--]]
# for循环解析多条数据
for i,v in pairs(res) do
ngx.say('username:'..v.username,'|','salary:'..v.salary)
ngx.say('<br/>')
end
end
ngx.say('err:',err)
ngx.say('<br/>')
ngx.say('errcode:',errcode)
ngx.say('<br/>')
ngx.say('sqlstate:',sqlstate)
db:close()
}
}

验证配置路由结果

image-20220609023333612

使用CJson编码数据table

修改Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# sudo vi /usr/local/openresty/nginx/conf/nginx.conf
location /mysqlQuery{
default_type 'text/html';
content_by_lua_block{
local mysql = require 'resty.mysql'
# 引入cjson模块, 也可以在http块中初始化
# init_by_lua_block{ cjson=require 'cjson' }
local cjson = require 'cjson'
local db = mysql:new()
local ok,err = db:connect{
host="192.168.253.134",
port=3306,
user="root",
password="xxxxxx",
database="nginx_db"
}
if not ok then
ngx.say('failed connected to mysql',err)
return
else
ngx.say('mysql connected success'..'<br/>')
end
db:set_timeout(1000)
db:send_query('select * from users')
local res,err,errcode,sqlstate = db:read_result()
if not err then
--[[
for i,v in pairs(res) do
ngx.say('username:'..v.username,'|','salary:'..v.salary)
ngx.say('<br/>')
end
--]]
local res_json = cjson.encode(res)
ngx.say('res_json: ',res_json)
ngx.say('<br/>')
end
ngx.say('err:',err)
ngx.say('<br/>')
ngx.say('errcode:',errcode)
ngx.say('<br/>')
ngx.say('sqlstate:',sqlstate)
db:close()
}
}

验证配置路由结果

image-20220609023722667

使用query()执行查询/读取

使用query()可以替代send_query()+read_result()

修改Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# sudo vi /usr/local/openresty/nginx/conf/nginx.conf
location /mysqlQuery{
default_type 'text/html';
content_by_lua_block{
local mysql = require 'resty.mysql'
local cjson = require 'cjson'
local db = mysql:new()
local ok,err = db:connect{
host="192.168.253.134",
port=3306,
user="root",
password="xxxxxx",
database="nginx_db"
}
if not ok then
ngx.say('failed connected to mysql',err)
return
else
ngx.say('mysql connected success'..'<br/>')
end
db:set_timeout(1000)
local sql = 'select * from users'
# 使用query()
local res,err,errcode,sqlstate = db:query(sql)
if res then
local res_json = cjson.encode(res)
ngx.say('res_json: ',res_json)
ngx.say('<br/>')
end
ngx.say('err:',err)
ngx.say('<br/>')
ngx.say('errcode:',errcode)
ngx.say('<br/>')
ngx.say('sqlstate:',sqlstate)
db:close()
}
}

增删改操作

增删改操作只需要将对于SQL放入query()中即可, 仅返回数据不同

修改Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# sudo vi /usr/local/openresty/nginx/conf/nginx.conf
location /mysqlQuery{
default_type 'text/html';
content_by_lua_block{
local mysql = require 'resty.mysql'
local cjson = require 'cjson'
local db = mysql:new()
local ok,err = db:connect{
host="192.168.253.134",
port=3306,
user="root",
password="xxxxxx",
database="nginx_db"
}
if not ok then
ngx.say('failed connected to mysql',err)
return
else
ngx.say('mysql connected success'..'<br/>')
end
db:set_timeout(1000)
-- local sql = "insert into users (username,birthday,salary) values ('aris','1998-12-07',22356)"
-- local sql = "update users set salary=100 where id=1"
local sql = "delete from users where username = 'aris'"
# 使用query()
local res,err,errcode,sqlstate = db:query(sql)
if res then
local res_json = cjson.encode(res)
ngx.say('res_json: ',res_json)
ngx.say('<br/>')
end
ngx.say('err:',err)
ngx.say('<br/>')
ngx.say('errcode:',errcode)
ngx.say('<br/>')
ngx.say('sqlstate:',sqlstate)
db:close()
}
}

验证结果

1
2
-- 新增
insert into users (username,birthday,salary) values ('aris','1998-12-07',22356)

image-20220609033006008

1
2
-- 修改
update users set salary=100 where id=1

image-20220609033232697

1
2
-- 删除
delete from users where username = 'aris'

image-20220609033404049

ngx_lua缓存预热

需求

使用ngx_lua做缓存预热. 访问路径http://192.168.253.138/cacheWarm?username=Tom, 不带参数时, 将所有数据缓存进Redis, 带参数时, 仅更新一条

修改配置

1
2
3
4
$ sudo mkdie /usr/local/openresty/nginx/lua_script
$ sudo vim /usr/local/openresty/nginx/lua_script/lua_init_script.lua
$ sudo vim /usr/local/openresty/nginx/lua_script/lua_cache_warm_script.lua
$ sudo vim /usr/local/openresty/nginx/conf/nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 修改Nginx配置文件
# sudo vim /usr/local/openresty/nginx/conf/nginx.conf
http {
...
init_by_lua_file /usr/local/openresty/nginx/lua_script/init_script.lua;
...
server {
...
location /cacheWarm{
default_type 'text/html';
content_by_lua_file /usr/local/openresty/nginx/lua_script/lua_cache_warm_script.lua;
}
}
}
1
2
3
4
5
-- 创建初始化脚本
-- sudo vim /usr/local/openresty/nginx/lua_script/lua_init_script.lua
redis = require 'resty.redis'
mysql = require 'resty.mysql'
cjson = require 'cjson'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
-- 创建业务逻辑脚本
-- sudo vim /usr/local/openresty/nginx/lua_script/lua_cache_warm_script.lua
-- 获取get参数username
local param = ngx.req.get_uri_args()['username'];

-- 连接数据库
local db = mysql:new()
local ok,err = db:connect{
host="192.168.253.134",
port=3306,
user="root",
password="xxxxxx",
database="nginx_db"
}
if not ok then
ngx.say("failed connect to mysql: ",err)
return
end
db:set_timeout(1000)

-- 依据get参数构建SQL
local sql = ""
if param then
sql = "select * from users where username = ".."'"..param.."'"
else
sql = "select * from users"
end

--执行SQL,获取数据
local res,err,errcode,sqlstate = db:query(sql)
if not res then
ngx.say("failed query in mysql: ",err)
return
end

-- 连接Redis
local redisObj = redis:new()
local ok,err = redisObj:connect("192.168.253.135",6379)
if not ok then
ngx.say("failed connect to redis: ",err)
return
end
redisObj:set_timeout(1000)

-- 循环MySQL数据存入Redis
local count=0
for i,v in ipairs(res) do
local redis_key = "user_"..v.username
local res_json = cjson.encode(v)
local ok,err = redisObj:set(redis_key,res_json)
if not ok then
ngx.say("failed set redis value: "..redis_key..'-'..res_json,err)
else
ngx.say("success set redis value: "..redis_key..'-'..res_json)
end
ngx.say("<br/>")
count = count + 1
end
ngx.say("warm cache success, total count "..count)

-- 关闭连接
db:close()
redisObj:close()

访问结果

1
访问 http://192.168.253.138/cacheWarm

image-20220609041921037

1
访问http://192.168.253.138/cacheWarm?username=Tom

image-20220609041936691

查看Redis缓存结果

image-20220609043004337