Openresty使用redis连接池

574次阅读
没有评论

共计 20943 个字符,预计需要花费 53 分钟才能阅读完成。

Openresty使用redis连接池

之前在使用lua-resty-redis模块调用redis时没有是使用连接池的方式,所以每一次需要调用redis的请求都会新建TCP链接。每一次新建断开都是要进行TCP三次握手四次挥手,耗费资源且低效,所以为了复用TCP链接,我们可以使用redis的链接池。设定一个固定链接池,每次调用完redis后不释放链接,而是将其放置回池中供后续使用

未使用链接池时,在redis中monitor指令查看状态,可以看到每次请求都是来自不同TCP链接

[root@nginx-cluster ~]# redis-cli -h 192.168.44.170
192.168.44.170:6379>
192.168.44.170:6379> MONITOR
OK
1631893230.044659 [0 192.168.44.145:57232] "sismember" "block-ip-list" "192.168.44.145"
1631893241.606487 [0 192.168.44.145:57236] "sismember" "block-ip-list" "192.168.44.145"
1631893257.586227 [0 192.168.44.145:57240] "sismember" "block-ip-list" "192.168.44.145"
1631893261.755798 [0 192.168.44.145:57244] "sismember" "block-ip-list" "192.168.44.145"

lua-resty-redis模块链接池

set_keepalive

syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size)

In case of success, returns 1. In case of errors, returns nil with a string describing the error.

将之前的例子在结束调用时增加以下行即可

                -- put it into the connection pool of size 100,
                -- with 10 seconds max idle time
                local ok, err = red:set_keepalive(10000, 100)
                if not ok then
                    ngx.say("failed to set keepalive: ", err)
                    return
                end

Only call this method in the place you would have called the close method instead. Calling this method will immediately turn the current redis object into the closed state. Any subsequent operations other than connect() on the current object will return the closed error

注意:使用了red:set_keepalive()后,之后的逻辑中若需要再次redis操作,需要重新发起connect(),相当于该方法自动带closed方法,不需要再接closed方法!

所以博主之前的写法稍微调整下

[root@nginx-cluster lua]# cat  ip_acl_redis3.lua
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000) -- 1 sec
local ok,err = red:connect("192.168.44.170",6379)
if not ok then
    ngx.say("failed to connect: ",err)
    return
end
ngx.log(ngx.INFO, " ok: ", ok, " type(ok): ", type(ok)," err: ", err)

--- 获取代理头部中透传的真实客户端地址
local headers=ngx.req.get_headers()
local ip = headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr

--- 判断ip是否set中的元素,若为真则返回为1
local res, err = red:sismember('block-ip-list', ip)
if 1 == res then
    ngx.log(ngx.INFO, "client ip in block-ip-list: ", ip)
    local ok, err = red:set_keepalive(60000, 1)
    ngx.exit(ngx.HTTP_FORBIDDEN)
else
    ngx.log(ngx.INFO, "client ip not in block-ip-list: ", ip)
    local ok, err = red:set_keepalive(60000, 1)
end

if not ok then
    ngx.say("failed to set keepalive: ", err)
    return
end

此时测试下访问情况,,注意连接池是工作进程级的,博主这里四个worker,所以可以看到有四个链接复用

1631894073.340721 [0 192.168.44.145:56380] "sismember" "block-ip-list" "192.168.44.145"
1631894082.390888 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894083.322968 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894084.159351 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894084.983031 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894085.783324 [0 192.168.44.145:56394] "sismember" "block-ip-list" "192.168.44.145"
1631894086.602929 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894087.413118 [0 192.168.44.145:56400] "sismember" "block-ip-list" "192.168.44.145"
1631894088.166519 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894088.943466 [0 192.168.44.145:56394] "sismember" "block-ip-list" "192.168.44.145"
1631894102.485094 [0 192.168.44.145:56400] "sismember" "block-ip-list" "192.168.44.145"
1631894103.288621 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894104.132416 [0 192.168.44.145:56400] "sismember" "block-ip-list" "192.168.44.145"
1631894104.944679 [0 192.168.44.145:56384] "sismember" "block-ip-list" "192.168.44.145"
1631894105.750793 [0 192.168.44.145:56380] "sismember" "block-ip-list" "192.168.44.145"

此时博主的连接池依然是1,即每个worker进程一个keepalive一个redis connect,如下图监控所示(存在探测链接2个,加上突然增加的4个keepalive链接共6个)

Openresty使用redis连接池

当我未调整进程池连接数时,如果此时并发超过链接池时,不会阻碍请求,也就是当链接池不够时,而是直接新建连接,只有4个连接会keepalive

[root@nginx-cluster conf.d]# ab -c 20 -n 20 http://192.168.44.145:8086/greating

# 对应日志
1631897280.687690 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897280.690025 [0 192.168.44.145:60950] "sismember" "block-ip-list" "192.168.44.145"
1631897280.690047 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897280.691149 [0 192.168.44.145:60968] "sismember" "block-ip-list" "192.168.44.145"
1631897280.691709 [0 192.168.44.145:60952] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692388 [0 192.168.44.145:32796] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692410 [0 192.168.44.145:32798] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692425 [0 192.168.44.145:32800] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692446 [0 192.168.44.145:32802] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692462 [0 192.168.44.145:32804] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692476 [0 192.168.44.145:32806] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692493 [0 192.168.44.145:32808] "sismember" "block-ip-list" "192.168.44.145"
1631897280.692506 [0 192.168.44.145:32810] "sismember" "block-ip-list" "192.168.44.145"
1631897280.696732 [0 192.168.44.145:32812] "sismember" "block-ip-list" "192.168.44.145"
1631897280.697052 [0 192.168.44.145:32814] "sismember" "block-ip-list" "192.168.44.145"
1631897280.697073 [0 192.168.44.145:32816] "sismember" "block-ip-list" "192.168.44.145"
1631897280.697721 [0 192.168.44.145:32818] "sismember" "block-ip-list" "192.168.44.145"
1631897280.699164 [0 192.168.44.145:32820] "sismember" "block-ip-list" "192.168.44.145"
1631897280.699267 [0 192.168.44.145:32822] "sismember" "block-ip-list" "192.168.44.145"
1631897280.699283 [0 192.168.44.145:32824] "sismember" "block-ip-list" "192.168.44.145"
1631897281.218788 [0 172.17.0.3:55382] "INFO" "ALL"
1631897282.220214 [0 172.17.0.3:55384] "INFO" "ALL"
1631897283.217621 [0 172.17.0.3:55386] "INFO" "ALL"
1631897284.220828 [0 172.17.0.3:55390] "INFO" "ALL"
1631897285.219402 [0 172.17.0.3:55394] "INFO" "ALL"
1631897286.220074 [0 172.17.0.3:55396] "INFO" "ALL"
1631897287.219696 [0 172.17.0.3:55398] "INFO" "ALL"
1631897288.217529 [0 172.17.0.3:55400] "INFO" "ALL"
1631897289.219929 [0 172.17.0.3:55402] "INFO" "ALL"
1631897289.473690 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897290.116170 [0 192.168.44.145:32796] "sismember" "block-ip-list" "192.168.44.145"
1631897290.217224 [0 172.17.0.3:55404] "INFO" "ALL"
1631897290.744571 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897291.218269 [0 172.17.0.3:55406] "INFO" "ALL"
1631897291.392570 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897292.038618 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897292.216908 [0 172.17.0.3:55408] "INFO" "ALL"
1631897292.649521 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897293.216575 [0 172.17.0.3:55414] "INFO" "ALL"
1631897293.384494 [0 192.168.44.145:60980] "sismember" "block-ip-list" "192.168.44.145"
1631897293.992413 [0 192.168.44.145:32796] "sismember" "block-ip-list" "192.168.44.145"

从上面日志输出来看,20并发超过pool_size=4设定,所以新建了连接,而后面用curl单次调用的链接则是pool中的链接。现在调整连接池为100后再测试,通过监控可以看到keepalive的链接为100

[root@nginx-cluster conf.d]# ab -c 100 -n 100 http://192.168.44.145:8086/greating
Openresty使用redis连接池

get_reused_times

syntax: times, err = red:get_reused_times()

This method returns the (successfully) reused times for the current connection. In case of error, it returns nil and a string describing the error.

If the current connection does not come from the built-in connection pool, then this method always returns 0, that is, the connection has never been reused (yet). If the connection comes from the connection pool, then the return value is always non-zero. So this method can also be used to determine if the current connection comes from the pool.

如果链接不是来自连接池,则返回0,若是则返回非0值。可以用来判断当前redis链接是否来自连接池。

微调下增加日志输出当前连接来源

[root@nginx-cluster lua]# cat ip_acl_redis3.lua
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000) -- 1 sec
local ok,err = red:connect("192.168.44.170",6379)
if not ok then
    ngx.say("failed to connect: ",err)
    return
end
ngx.log(ngx.INFO, " ok: ", ok, " type(ok): ", type(ok)," err: ", err)

--- 获取代理头部中透传的真实客户端地址
local headers=ngx.req.get_headers()
local ip = headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr

--- 判断ip是否set中的元素,若为真则返回为1
local res, err = red:sismember('block-ip-list', ip)
local times, terr = red:get_reused_times()
if times then
    ngx.log(ngx.INFO, "times: ", times)
end
if 1 == res then
    ngx.log(ngx.INFO, "client ip in block-ip-list: ", ip)
    local ok, err = red:set_keepalive(60000, 1)
    ngx.exit(ngx.HTTP_FORBIDDEN)
else
    ngx.log(ngx.INFO, "client ip not in block-ip-list: ", ip)
    local ok, err = red:set_keepalive(60000, 1)
end

if not ok then
    ngx.say("failed to set keepalive: ", err)
    return
end

对应日志

2021/09/18 18:06:07 [info] 31819#0: *55 [lua] ip_acl_redis3.lua:19: times: 2, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31819#0: *55 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *51 [lua] ip_acl_redis3.lua:19: times: 1, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *51 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *48 [lua] ip_acl_redis3.lua:19: times: 1, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31819#0: *65 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *48 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31819#0: *65 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31819#0: *58 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31819#0: *58 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *64 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *64 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *61 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *61 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *66 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *66 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *57 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *57 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *50 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *50 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *63 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *63 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *49 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *49 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *62 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *62 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *60 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *60 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *59 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *59 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *54 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31820#0: *54 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31818#0: *52 [lua] ip_acl_redis3.lua:19: times: 1, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31818#0: *52 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31818#0: *56 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31818#0: *56 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31818#0: *53 [lua] ip_acl_redis3.lua:19: times: 0, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31818#0: *53 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.0", host: "192.168.44.145:8086"
2021/09/18 18:06:07 [info] 31817#0: *67 client closed connection while waiting for request, client: 192.168.44.145, server: 0.0.0.0:8086
2021/09/18 18:06:59 [info] 31819#0: *83 [lua] ip_acl_redis3.lua:9:  ok: 1 type(ok): number err: nil, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.1", host: "192.168.44.145:8086"
2021/09/18 18:06:59 [info] 31819#0: *83 [lua] ip_acl_redis3.lua:19: times: 1, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.1", host: "192.168.44.145:8086"
2021/09/18 18:06:59 [info] 31819#0: *83 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.1", host: "192.168.44.145:8086"
2021/09/18 18:06:59 [info] 31819#0: *83 client 192.168.44.145 closed keepalive connection
2021/09/18 18:07:07 [info] 31818#0: *84 [lua] ip_acl_redis3.lua:9:  ok: 1 type(ok): number err: nil, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.1", host: "192.168.44.145:8086"
2021/09/18 18:07:07 [info] 31818#0: *84 [lua] ip_acl_redis3.lua:19: times: 1, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.1", host: "192.168.44.145:8086"
2021/09/18 18:07:07 [info] 31818#0: *84 [lua] ip_acl_redis3.lua:26: client ip not in block-ip-list: 192.168.44.145, client: 192.168.44.145, server: , request: "GET /sayHello HTTP/1.1", host: "192.168.44.145:8086"
2021/09/18 18:07:07 [info] 31818#0: *84 client 192.168.44.145 closed keepalive connection

openresty对原redis模块二次封装

网上有一个很不错的封装,对比我之前写的,算了不比了 ε(┬┬﹏┬┬)3

[root@nginx-cluster lua]# cat cat comm/redis_iresty.lua
local redis_c = require "resty.redis"

local ok, new_tab = pcall(require, "table.new")
if not ok or type(new_tab) ~= "function" then
                new_tab = function (narr, nrec) return {} end
end

local _M = new_tab(0, 155)
_M._VERSION = '0.01'

local commands = {
                "append",            "auth",              "bgrewriteaof",
                "bgsave",            "bitcount",          "bitop",
                "blpop",             "brpop",
                "brpoplpush",        "client",            "config",
                "dbsize",
                "debug",             "decr",              "decrby",
                "del",               "discard",           "dump",
                "echo",
                "eval",              "exec",              "exists",
                "expire",            "expireat",          "flushall",
                "flushdb",           "get",               "getbit",
                "getrange",          "getset",            "hdel",
                "hexists",           "hget",              "hgetall",
                "hincrby",           "hincrbyfloat",      "hkeys",
                "hlen",
                "hmget",              "hmset",      "hscan",
                "hset",
                "hsetnx",            "hvals",             "incr",
                "incrby",            "incrbyfloat",       "info",
                "keys",
                "lastsave",          "lindex",            "linsert",
                "llen",              "lpop",              "lpush",
                "lpushx",            "lrange",            "lrem",
                "lset",              "ltrim",             "mget",
                "migrate",
                "monitor",           "move",              "mset",
                "msetnx",            "multi",             "object",
                "persist",           "pexpire",           "pexpireat",
                "ping",              "psetex",            "psubscribe",
                "pttl",
                "publish",      --[[ "punsubscribe", ]]   "pubsub",
                "quit",
                "randomkey",         "rename",            "renamenx",
                "restore",
                "rpop",              "rpoplpush",         "rpush",
                "rpushx",            "sadd",              "save",
                "scan",              "scard",             "script",
                "sdiff",             "sdiffstore",
                "select",            "set",               "setbit",
                "setex",             "setnx",             "setrange",
                "shutdown",          "sinter",            "sinterstore",
                "sismember",         "slaveof",           "slowlog",
                "smembers",          "smove",             "sort",
                "spop",              "srandmember",       "srem",
                "sscan",
                "strlen",       --[[ "subscribe",  ]]     "sunion",
                "sunionstore",       "sync",              "time",
                "ttl",
                "type",         --[[ "unsubscribe", ]]    "unwatch",
                "watch",             "zadd",              "zcard",
                "zcount",            "zincrby",           "zinterstore",
                "zrange",            "zrangebyscore",     "zrank",
                "zrem",              "zremrangebyrank",   "zremrangebyscore",
                "zrevrange",         "zrevrangebyscore",  "zrevrank",
                "zscan",
                "zscore",            "zunionstore",       "evalsha"
}

local mt = { __index = _M }

local function is_redis_null( res )
                if type(res) == "table" then
                                for k,v in pairs(res) do
                                                if v ~= ngx.null then
                                                                return false
                                                end
                                end
                                return true
                elseif res == ngx.null then
                                return true
                elseif res == nil then
                                return true
                end

                return false
end

function _M.connect_mod(self)
        local redis, err = redis_c:new()
        if not redis or err then
                return nil, err
        end

        redis:set_timeout(self.timeout)
        local ok, err = redis:connect(self.host, self.port)
        if not ok or err then
                return nil, err
        end

        if self.password then
                local times, err = redis:get_reused_times()
                if times == 0 then
                        local ok, err = redis:auth(self.password)
                        if not ok or err then
                                return nil, err
                        end
                elseif err then
                        return nil, err
                end
        end

        return redis, nil
end


function _M.set_keepalive_mod(self, redis)
        return redis:set_keepalive(self.keepalive, self.pool_size)
end


function _M.init_pipeline(self)
        self._reqs = {}
end


function _M.commit_pipeline(self)
        local reqs = self._reqs

        if reqs == nil or #reqs == 0 then
                return {}, 'no pipeline'
        else
                self._reqs = nil
        end

        local redis, err = self:connect_mod()
        if not redis or err then
                return {}, err
        end

        redis:init_pipeline()
        for _, v in ipairs(reqs) do
                local method = redis[v[1]]
                table.remove(v, 1)
                method(redis, unpack(v))
        end

        local results, err = redis:commit_pipeline()
        if not results or err then
                return {}, err
        end

        if is_redis_null(results) then
                results = {}
        end

        local ok, err = self:set_keepalive_mod(redis)
        if not ok or err then
                return {}, err
        end

        for k, v in ipairs(results) do
                if is_redis_null(v) then
                        results[k] = nil
                end
        end

        return results, nil
end


function _M.subscribe(self, channel)
        local redis, err = self:connect_mod()
        if not redis or err then
                return {}, err
        end

        local res, err = redis:subscribe(channel)
        if not res or err then
                return nil, err
        end

        local function do_read_func(do_read)
                if do_read == nil or do_read == true then
                        local res, err = redis:read_reply()
                        if not res or err then
                                return nil, err
                        end
                        return res
                end

                redis:unsubscribe(channel)
                self.set_keepalive_mod(redis)
                return
        end

        return do_read_func
end

local function do_command(self, cmd, ...)
        if self._reqs then
                self._reqs:insert({cmd, ...})
                return
        end

        local redis, err = self:connect_mod()
        if not redis or err then
                return {}, err
        end

        local method = redis[cmd]
        local result, err = method(redis, ...)
        if not result or err then
                return nil, err
        end

        if is_redis_null(result) then
                result = nil
        end

        local ok, err = self:set_keepalive_mod(redis)
        if not ok or err then
                return nil, err
        end

        return result, nil
end

function _M.new(self, opts)
        opts.host = opts.host or '127.0.0.1'
        opts.port = opts.port or 6379
        opts.db = opts.db or 0
        opts.password = opts.password or nil
        opts.timeout = opts.timeout or 1000
        opts.keepalive = opts.keepalive or 60000
        opts.pool_size = opts.pool_size or 100
        opts._reqs = nil

        for i = 1, #commands do
                local cmd = commands[i]
                _M[cmd] =
                        function (self, ...)
                                return do_command(self, cmd, ...)
                        end
        end

        return setmetatable(opts, mt)
end

return _M

查看上面封装的模块中的function _M.new(self, opts)

[root@nginx-cluster lua]# cat ip_acl_redis4.lua
local redis = require "comm.redis_iresty"
local opts = {
    host = "192.168.44.170",
    port = "6379",
    db = 0,
    keepalive = 60000,
    pool_size = 200,
}
local red = redis:new(opts)

--- 获取代理头部中透传的真实客户端地址
local headers=ngx.req.get_headers()
local ip = headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr


--- 判断ip是否set中的元素,若为真则返回为1
local res, err = red:sismember('block-ip-list', ip)
if 1 == res then
    ngx.log(ngx.INFO, "client ip in block-ip-list: ", ip)
    ngx.exit(ngx.HTTP_FORBIDDEN)
else
    ngx.log(ngx.INFO, "client ip not in block-ip-list: ", ip)
end

对应的location

    location /sayHello {
        access_by_lua_file lua/ip_acl_redis3.lua;
        content_by_lua_block {
            ngx.say("Allow Operating")
            ngx.exit(ngx.OK)
        }
    }
    location /greating {
        access_by_lua_file lua/ip_acl_redis4.lua;
        content_by_lua_block {
            ngx.say("Allow Operating")
            ngx.exit(ngx.OK)
        }
    }

正文完
 
xadocker
版权声明:本站原创文章,由 xadocker 2021-09-19发表,共计20943字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)