-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(plugins) don't call redis:select when not necessary #3973
fix(plugins) don't call redis:select when not necessary #3973
Conversation
In plugin rate-limiting and response-ratelimiting, a redis:select is called when connection is reused, even though the current configured redis database is 0, to clear the previously selected database. This will be problem when for some use case like twemproxy where select is not supported, and sending `select` call will cause the connection to be closed. The patch used a host+port+database based redis connection pool, so that we always know the current connection is using correct database.
-- return a special pool name only if redis_database is set to non-zero | ||
-- otherwise use the default pool name host:port | ||
if conf.redis_database ~= 0 then | ||
local key = fmt("%s:%d:%d", conf.redis_port, conf.redis_port, conf.redis_database) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second argument here should be conf.redis_host
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, prior art has proven that a simple concat operation could perform as well or better than string.format
, we should maybe follow this new rule of thumb.
@@ -136,7 +145,8 @@ return { | |||
increment = function(conf, limits, identifier, current_timestamp, value) | |||
local red = redis:new() | |||
red:set_timeout(conf.redis_timeout) | |||
local ok, err = red:connect(conf.redis_host, conf.redis_port) | |||
local ok, err = red:connect(conf.redis_host, conf.redis_port, | |||
{ pool = get_redis_pool_name(conf) }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could reuse this table (if declared at the top chunk level) and just override its pool
property, to save some GC overhead, and some function call overhead as well:
sock_opts.pool = get_redis_pool_name(conf) -- could even be inlined
Nice catch :) Meant to request some changes, but mis-clicked. Additionally, note that the linter is failing in CI. |
@thibaultcha Thank you for reviewing this, I've addressed the comments and CI is green now. Could you take another look when you got chance? |
if not ok then | ||
ngx_log(ngx.ERR, "failed to change Redis database: ", err) | ||
return nil, err | ||
local ok, err = red:select(conf.redis_database or 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably dont need the or 0
here?
LGTM, however we should wait until our Travis CI issues are resolved before merging this. |
Hi @thibaultcha, do we have an update on the CI issue? |
@fffonion It should be fine if you rebase this branch on the latest master. |
Running green on |
Summary
In plugin rate-limiting and response-ratelimiting, a redis:select is
called when connection is reused, even though the current configured
redis database is 0, to clear the previously selected database. This
will be problem for some use case like twemproxy where
select
isnot supported, and sending
select
call will cause the connection tobe closed.
The patch used a host+port+database based redis connection pool, so that
we always know the current connection is using correct database. The
behaviour of redis:auth only once is not changed.
Full changelog
select
callIssues resolved
Related to #3293