Nginx+Lua实现分布式缓存

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
local redis = require("resty.redis")
local cjson = require("cjson")
local cjson_encode = cjson.encode
local ngx_log = ngx.log
local ngx_ERR = ngx.ERR
local ngx_exit = ngx.exit
local ngx_print = ngx.print
local ngx_re_match = ngx.re.match
local ngx_var = ngx.var

local function close_redis(red)
if not red then
return
end
-- 释放连接(连接池实现)
local pool_max_idle_time = 10000 -- 毫秒
local pool_size = 100 -- 连接池大小
local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)

if not ok then
ngx_log(ngx_ERR, "set redis keepalive error : ", err)
end
end

local function read_redis(id)
local red = redis:new()
red:set_timeout(1000)
local ip = "127.0.0.1"
local port = 1111
local ok, err = red:connect(ip, port)
if not ok then
ngx_log(ngx_ERR, "connect to redis error : ", err)
return close_redis(red)
end

local resp, err = red:get(id)
if net resp then
ngx_log(ngx_ERR, "get redis connect error : ", err)
return close_redis(red)
end
-- 得到的数据为空处理
if resp == ngx.null then
resp = nil
end
close_redis(red)

return resp
end

local function read_http(id)
local resp = ngx.location.capture("/backend", {
method = ngx.HTTP_GET,
args = {id = id}
})

if not resp then
ngx_log(ngx_ERR, "request error :", err)
return
end

if resp.status ~= 200 then
ngx_log(ngx_ERR, "request error, status :", resp.status)
return
end

return resp.body
end

-- 获取id
local id = ngx_var.id

-- 从redis获取
local content = read_redis(id)

-- 如果redis没有,则回源到tomcat
if not content then
ngx_log(ngx_ERR, "redis not found content, back to http, id : ", id)
content = read_http(id)
end

-- 如果还没有,则返回404
if not content then
ngx_log(ngx_ERR, "http not found content, id : ", id)
return ngx_exit(404)
end

-- 输出内容
ngx.print("show_ad(")
ngx.print(cjson_encode({content = content}))
ngx.print(")")