-
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
Pdk refine with optional cache to improvement performance #13981
base: master
Are you sure you want to change the base?
Conversation
…tent_type replacement
f5f8ba9
to
71e2a62
Compare
_G.ngx.req.read_body = function() | ||
-- for the same request, only one `read_body` call is needed | ||
if not ngx.ctx.body_read then | ||
read_req_body() |
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.
ngx.req.read_body
only need to be called once in a request lifetime. Although multiple calls in the same request
don't re-read data to buffer multiple times, there are still some extra cost of check logic. So we could just avoid it to gain better performance.
@@ -98,7 +96,7 @@ local function new(self) | |||
function _REQUEST.get_scheme() | |||
check_phase(PHASES.request) | |||
|
|||
return var.scheme | |||
return ngx.ctx.scheme or var.scheme |
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.
ctx
is cheaper then var
, so use ctx
if exists, like what we do in router handling: local req_scheme = ctx and ctx.scheme or var.scheme
kong/pdk/request.lua
Outdated
@@ -619,14 +617,14 @@ local function new(self) | |||
-- kong.request.get_header("Host") -- "foo.com" | |||
-- kong.request.get_header("x-custom-header") -- "bla" | |||
-- kong.request.get_header("X-Another") -- "foo bar" | |||
function _REQUEST.get_header(name) | |||
function _REQUEST.get_header(name, ctx) |
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.
http_get_header
supports ctx
param to cache headers, expose it to get_header
API so we could use cache.
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.
I don't like this either. If we add this parameter, we need to always keep the API like that, that the second parameter needs to be ctx
. The benefits are so small that I would rather not do it. The most of the changes in plugins seems to be utilizing this. And that is also I think somewhat "bad" code to make people create tables of ctx and pass it here. If we cannot find better way to do this, then I would not do it.
Just an example e.g. if someone wants to add more beneficial parameter lilke default
in case the header is missing the code would become:
local value = kong.request.get_header("Some-Header", nil, "default")
Perhaps we will never add that either, but just tells that we don't want these strange ctx
parameters in public API.
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.
What if we use kong.tools.get_header(name, ctx)
directly in plugins, to replace non-cached kong.request.get_header
API in certain places to achieve the cache benefit? It must be better to use PDK APIs in plugins, but I do see that there are a lot of kong.tools
usage in plugins(which I feel more like should be used "internally" in core or some non-plugin module?), Do you think it's a proper practice?
@@ -820,8 +818,7 @@ local function new(self) | |||
-- body.age -- "42" | |||
function _REQUEST.get_body(mimetype, max_args, max_allowed_file_size) | |||
check_phase(before_content) | |||
|
|||
local content_type = mimetype or _REQUEST.get_header(CONTENT_TYPE) | |||
local content_type = mimetype or ngx.var.http_content_type |
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.
"Content-Type" is a built-in single value header, which means ngx.var.http_content_type
always returns the same value of get_header("Content-Type")
, and fetching single header by ngx.var
is quicker than get_header
(which may use get_headers()["Content-Type"]
to get the single header).
kong/pdk/service/response.lua
Outdated
@@ -285,10 +285,11 @@ local function new(pdk, major_version) | |||
-- -- or `access` phase prior calling this function. | |||
-- | |||
-- local body = kong.service.response.get_raw_body() | |||
function response.get_raw_body() | |||
function response.get_raw_body(buffered_proxying) |
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.
just a minor refinement so that if we could reduce the reads of ngx.ctx.buffered_proxying
by passing it by param
kong/plugins/basic-auth/access.lua
Outdated
@@ -158,21 +158,22 @@ end | |||
|
|||
local function do_authentication(conf) | |||
local www_authenticate = "Basic realm=\"" .. conf.realm .. "\"" | |||
local ctx = {} |
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.
Use a local ctx
here which is cheaper thanngx.ctx
, and the cache is only fresh in the local ctx
lifetime, not in the request lifetime, so we don't need ngx.ctx
kong/pdk/service/response.lua
Outdated
check_phase(header_body_log) | ||
local ctx = ngx.ctx | ||
if not ctx.buffered_proxying then | ||
local buffered = buffered_proxying or ctx.buffered_proxying |
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.
I am not sure about that. Adding buffered_proxying
as public interface parameter feels a bit wrong. Also what if someone passes false
here?
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.
I am not sure about that. Adding
buffered_proxying
as public interface parameter feels a bit wrong. Also what if someone passesfalse
here?
Yes this seems a little bit confused if users pass in false
but we will still respect the ctx.bufferred_proxying
.
My intention was to reduce the read of ctx
, because local variable is faster than ctx
, and when invoking get_raw_body
inside get_body
I could just pass in the ctx.bufferd_proxying
we've read already.
I think we can revert the get_raw_body
change, and inside the get_body
function, just replace the get_raw_body
call with return ctx.buffered_body or ""
, because we already do the check_phase
and ctx.buffered_proxying
check, what do you think?
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.
Yes, I would revert these PDK API changes (where we add new parameters). Not worth it, and paints us in a corner.
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.
Let's revert all the API changes and related changes in where the changed APIs were used. Benefit vs. drawbacks are too small. Those optimizations can be implemented inside plugins themselves if they are that good. In many cases it also depends whether plugin is reading single or multiple headers to what to use, eg. is. get_headers better than multiple get_header and is multiple get_header better with created context table at what count?
kong/pdk/request.lua
Outdated
@@ -619,14 +617,14 @@ local function new(self) | |||
-- kong.request.get_header("Host") -- "foo.com" | |||
-- kong.request.get_header("x-custom-header") -- "bla" | |||
-- kong.request.get_header("X-Another") -- "foo bar" | |||
function _REQUEST.get_header(name) | |||
function _REQUEST.get_header(name, ctx) |
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.
I don't like this either. If we add this parameter, we need to always keep the API like that, that the second parameter needs to be ctx
. The benefits are so small that I would rather not do it. The most of the changes in plugins seems to be utilizing this. And that is also I think somewhat "bad" code to make people create tables of ctx and pass it here. If we cannot find better way to do this, then I would not do it.
Just an example e.g. if someone wants to add more beneficial parameter lilke default
in case the header is missing the code would become:
local value = kong.request.get_header("Some-Header", nil, "default")
Perhaps we will never add that either, but just tells that we don't want these strange ctx
parameters in public API.
kong/pdk/service/response.lua
Outdated
check_phase(header_body_log) | ||
local ctx = ngx.ctx | ||
if not ctx.buffered_proxying then | ||
local buffered = buffered_proxying or ctx.buffered_proxying |
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.
Yes, I would revert these PDK API changes (where we add new parameters). Not worth it, and paints us in a corner.
Removed all public API changes. @bungle |
Summary
Checklist
changelog/unreleased/kong
orskip-changelog
label added on PR if changelog is unnecessary. README.mdIssue reference
Fix #[issue number]