Skip to content
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

feat(timerng) integrate the lua-resty-timer-ng #8912

Merged
merged 1 commit into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,18 @@

### Additions

#### Performance
- Do not register unnecessary event handlers on Hybrid mode Control Plane
nodes [#8452](https://github.com/Kong/kong/pull/8452).
- Use the new timer library to improve performance,
except for the plugin server.
[8912](https://github.com/Kong/kong/pull/8912)

#### Admin API

- Added a new API `/timers` to get the timer statistics.
[8912](https://github.com/Kong/kong/pull/8912)

#### Core

- Added `cache_key` on target entity for uniqueness detection.
Expand Down Expand Up @@ -279,12 +291,6 @@ a restart (e.g., upon a plugin server crash).
instead of `proxy_error_log` [8583](https://github.com/Kong/kong/pull/8583)


### Additions

#### Performance
- Do not register unnecessary event handlers on Hybrid mode Control Plane
nodes [#8452](https://github.com/Kong/kong/pull/8452).

## [2.8.0]

### Deprecations
Expand Down
1 change: 1 addition & 0 deletions kong-2.8.0-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dependencies = {
"lua-resty-ipmatcher == 0.6.1",
"lua-resty-acme == 0.8.0",
"lua-resty-session == 3.10",
"lua-resty-timer-ng == 0.1.0",
}
build = {
type = "builtin",
Expand Down
5 changes: 5 additions & 0 deletions kong/api/routes/kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,9 @@ return {
return kong.response.exit(200, copy)
end
},
["/timers"] = {
GET = function (self, db, helpers)
return kong.response.exit(200, _G.timerng_stats())
end
}
}
44 changes: 44 additions & 0 deletions kong/globalpatches.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,50 @@ return function(options)
end


do
_G.native_timer_at = ngx.timer.at
_G.native_timer_every = ngx.timer.every

local timerng

if options.cli or options.rbusted then
timerng = require("resty.timerng").new({
min_threads = 16,
max_threads = 32,
})

timerng:start()

else
timerng = require("resty.timerng").new()

-- TODO rename
_G.timerng_start = function (debug)
timerng:start()
timerng:set_debug(debug)
end

end

_G.ngx.timer.at = function (delay, callback, ...)
return timerng:at(delay, callback, ...)
end

_G.ngx.timer.every = function (interval, callback, ...)
return timerng:every(interval, callback, ...)
end

-- TODO rename
_G.timerng_stats = function ()
return timerng:stats({
verbose = true,
flamegraph = true,
})
end

end



do -- implement a Lua based shm for: cli (and hence rbusted)

Expand Down
1 change: 1 addition & 0 deletions kong/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ function Kong.init_worker()
-- duplicated seeds.
math.randomseed()

_G.timerng_start(kong.configuration.log_level == "debug")

-- init DB

Expand Down
5 changes: 2 additions & 3 deletions kong/runloop/plugin_servers/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ local kong = kong
local ngx_var = ngx.var
local coroutine_running = coroutine.running
local get_plugin_info = proc_mgmt.get_plugin_info
local ngx_timer_at = ngx.timer.at
local subsystem = ngx.config.subsystem

--- keep request data a bit longer, into the log timer
Expand Down Expand Up @@ -250,7 +249,7 @@ local function build_phases(plugin)
response_status = ngx.status,
}

ngx_timer_at(0, function()
_G.native_timer_at(0, function()
local co = coroutine_running()
save_for_later[co] = saved

Expand Down Expand Up @@ -322,7 +321,7 @@ function plugin_servers.start()

for _, server_def in ipairs(proc_mgmt.get_server_defs()) do
if server_def.start_command then
ngx_timer_at(0, pluginserver_timer, server_def)
_G.native_timer_at(0, pluginserver_timer, server_def)
end
end
end
Expand Down
18 changes: 16 additions & 2 deletions spec/01-unit/01-db/08-cache_warmup_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local cache_warmup = require("kong.cache.warmup")
local helpers = require("spec.helpers")


local function mock_entity(db_data, entity_name, cache_key)
Expand Down Expand Up @@ -211,9 +212,15 @@ describe("cache_warmup", function()

cache_warmup._mock_kong(kong)

local runs_old = _G.timerng_stats().sys.runs

assert.truthy(cache_warmup.execute({"my_entity", "services"}))

ngx.sleep(0) -- yield so that async DNS caching happens
-- waiting async DNS cacheing
helpers.wait_until(function ()
ADD-SP marked this conversation as resolved.
Show resolved Hide resolved
local runs = _G.timerng_stats().sys.runs
return runs_old < runs
end)

-- `my_entity` isn't a core entity; lookup is on client cache
assert.same(kong.cache:get("111").bbb, 222)
Expand Down Expand Up @@ -264,9 +271,15 @@ describe("cache_warmup", function()

cache_warmup._mock_kong(kong)

local runs_old = _G.timerng_stats().sys.runs

assert.truthy(cache_warmup.execute({"my_entity", "services"}))

ngx.sleep(0.001) -- yield so that async DNS caching happens
-- waiting async DNS cacheing
helpers.wait_until(function ()
local runs = _G.timerng_stats().sys.runs
return runs_old < runs
end)

-- `my_entity` isn't a core entity; lookup is on client cache
assert.same(kong.cache:get("111").bbb, 222)
Expand All @@ -279,6 +292,7 @@ describe("cache_warmup", function()

-- skipped IP entry
assert.same({ "example.com", "example.test" }, dns_queries)

end)


Expand Down
35 changes: 23 additions & 12 deletions spec/02-integration/02-cmd/02-start_stop_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ describe("kong start/stop #" .. strategy, function()
end)
after_each(function()
helpers.kill_all()
os.execute("rm -rf " .. helpers.test_conf.prefix .. "/worker_events.sock")
end)

lazy_teardown(function()
helpers.clean_prefix()
end)
Expand Down Expand Up @@ -178,6 +180,10 @@ describe("kong start/stop #" .. strategy, function()
end)

describe("verbose args", function()
after_each(function ()
os.execute("rm -rf " .. helpers.test_conf.prefix .. "/worker_events.sock")
end)

it("accepts verbose --v", function()
local _, _, stdout = assert(helpers.kong_exec("start --v --conf " .. helpers.test_conf_path))
assert.matches("[verbose] prefix in use: ", stdout, nil, true)
Expand Down Expand Up @@ -226,18 +232,23 @@ describe("kong start/stop #" .. strategy, function()
end)

describe("/etc/hosts resolving in CLI", function()
it("resolves #cassandra hostname", function()
assert(helpers.kong_exec("start --vv --run-migrations --conf " .. helpers.test_conf_path, {
cassandra_contact_points = "localhost",
database = "cassandra"
}))
end)
it("resolves #postgres hostname", function()
assert(helpers.kong_exec("start --conf " .. helpers.test_conf_path, {
pg_host = "localhost",
database = "postgres"
}))
end)
if strategy == "cassandra" then
it("resolves #cassandra hostname", function()
assert(helpers.kong_exec("start --vv --run-migrations --conf " .. helpers.test_conf_path, {
cassandra_contact_points = "localhost",
database = "cassandra"
}))
end)

elseif strategy == "postgres" then
it("resolves #postgres hostname", function()
assert(helpers.kong_exec("start --conf " .. helpers.test_conf_path, {
pg_host = "localhost",
database = "postgres"
}))
end)
end

end)

-- TODO: update with new error messages and behavior
Expand Down
2 changes: 1 addition & 1 deletion spec/02-integration/02-cmd/08-quit_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ describe("kong quit", function()
assert(helpers.kong_exec("quit --wait 2 --prefix " .. helpers.test_conf.prefix))
ngx.update_time()
local duration = ngx.now() - start
assert.is.near(2, duration, 1.6)
assert.is.near(2, duration, 2.5)
end)
end)
7 changes: 6 additions & 1 deletion spec/02-integration/03-db/09-query-semaphore_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,18 @@ describe("#postgres Postgres query locks", function()
end)

it("results in query error failing to acquire resource", function()
local wait_timers_ctx = helpers.wait_timers_begin()

local res = assert(client:send {
method = "GET",
path = "/slow-resource?prime=true",
headers = { ["Content-Type"] = "application/json" }
})
assert.res_status(204 , res)

-- make a request that would run a query while no resources are available
-- wait for zero-delay timer
helpers.wait_timers_end(wait_timers_ctx, 0.5)

res = assert(client:send {
method = "GET",
path = "/slow-resource",
Expand All @@ -49,5 +53,6 @@ describe("#postgres Postgres query locks", function()
local body = assert.res_status(500 , res)
local json = cjson.decode(body)
assert.same({ error = "error acquiring query semaphore: timeout" }, json)

end)
end)
54 changes: 54 additions & 0 deletions spec/02-integration/04-admin_api/20-timers_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
local helpers = require "spec.helpers"
local cjson = require "cjson"


for _, strategy in helpers.each_strategy() do

describe("Admin API[#" .. strategy .. "]" , function()
local client

lazy_setup(function()
helpers.get_db_utils(strategy)

assert(helpers.start_kong({
database = strategy,
nginx_conf = "spec/fixtures/custom_nginx.template",
}))

client = helpers.admin_client()
end)

teardown(function()
if client then
client:close()
end
helpers.stop_kong()
end)

it("/timers", function ()
local res = assert(client:send {
method = "GET",
path = "/timers",
headers = { ["Content-Type"] = "application/json" }
})

local body = assert.res_status(200 , res)
local json = cjson.decode(body)

assert(type(json.flamegraph.running) == "string")
assert(type(json.flamegraph.pending) == "string")
assert(type(json.flamegraph.elapsed_time) == "string")

assert(type(json.sys.total) == "number")
assert(type(json.sys.runs) == "number")
assert(type(json.sys.running) == "number")
assert(type(json.sys.pending) == "number")
assert(type(json.sys.waiting) == "number")

assert(type(json.timers) == "table")

end)

end)

end
8 changes: 7 additions & 1 deletion spec/02-integration/05-proxy/02-router_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ local function insert_routes(bp, routes)
local cfg = bp.done()
local yaml = declarative.to_yaml_string(cfg)
local admin_client = helpers.admin_client()

local wait_timers_ctx = helpers.wait_timers_begin()

local res = assert(admin_client:send {
method = "POST",
path = "/config",
Expand All @@ -85,9 +88,12 @@ local function insert_routes(bp, routes)
assert.res_status(201, res)
admin_client:close()

-- wait for timers finish
helpers.wait_timers_end(wait_timers_ctx, 0.5)
end

ngx.sleep(0.01) -- temporary wait
ngx.sleep(0.01) -- temporary wait for worker events

return routes
end

Expand Down
Loading