membphis commented on code in PR #12872:
URL: https://github.com/apache/apisix/pull/12872#discussion_r2715579601
##########
apisix/plugins/limit-conn/util.lua:
##########
@@ -18,36 +18,66 @@
local assert = assert
local math = require "math"
local floor = math.floor
+local ngx = ngx
+local ngx_time = ngx.time
+local uuid = require("resty.jit-uuid")
+
local _M = {version = 0.3}
+local redis_incoming_script = [[
+ local key = KEYS[1]
+ local limit = tonumber(ARGV[1])
+ local ttl = tonumber(ARGV[2])
+ local now = tonumber(ARGV[3])
+ local req_id = ARGV[4]
+
+ redis.call('ZREMRANGEBYSCORE', key, 0, now)
+
+ local count = redis.call('ZCARD', key)
+ if count >= limit then
+ return {0, count}
+ end
+
+ redis.call('ZADD', key, now + ttl, req_id)
+ redis.call('EXPIRE', key, ttl)
+ return {1, count + 1}
+]]
function _M.incoming(self, red, key, commit)
local max = self.max
self.committed = false
+ local raw_key = key
key = "limit_conn" .. ":" .. key
- local conn, err
+ local conn
if commit then
- conn, err = red:incrby(key, 1)
- if not conn then
+ local req_id = ngx.ctx.request_id or uuid.generate_v4()
+ if not ngx.ctx.limit_conn_req_ids then
+ ngx.ctx.limit_conn_req_ids = {}
+ end
+ ngx.ctx.limit_conn_req_ids[raw_key] = req_id
+
+ local now = ngx_time()
+ local res, err = red:eval(redis_incoming_script, 1, key,
Review Comment:
you can take a look at this example, which is better performance
we can cache the `sha1` of Lua script, then we call `evalsha`
```lua
local redis = require "resty.redis"
local red = redis:new()
-- 1. Define your fixed script and pre-calculate its SHA1 locally
-- You can use an online SHA1 tool or calculate it via code
local script_content = "return redis.call('GET', KEYS[1])"
local script_sha1 = "6bce267422d7793d3e0034d7c99602029c5737e6"
red:set_timeout(1000) -- 1 sec
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect: ", err)
return
end
--- Function to execute script with EVALSHA optimization
local function optimized_eval(red, sha1, script, num_keys, ...)
-- Try EVALSHA first
local res, err = red:evalsha(sha1, num_keys, ...)
-- If the script is missing in Redis (NOSCRIPT error)
if not res and err and string.find(err, "NOSCRIPT") then
ngx.log(ngx.INFO, "Script not found in cache, loading now...")
-- Load the script to get the SHA1 (or verify it)
local new_sha, load_err = red:script("LOAD", script)
if not new_sha then
return nil, "failed to load script: " .. (load_err or "")
end
-- Retry EVALSHA with the loaded script
return red:evalsha(new_sha, num_keys, ...)
end
return res, err
end
-- 2. Call the function
local res, err = optimized_eval(red, script_sha1, script_content, 1,
"my_key")
if not res then
ngx.say("Error: ", err)
else
ngx.say("Result: ", res)
end
-- Put it back in the connection pool
red:set_keepalive(10000, 100)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]