Skip to content
Draft
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
3 changes: 2 additions & 1 deletion apisix/cli/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ local _M = {
normalize_uri_like_servlet = false,
router = {
http = "radixtree_host_uri",
ssl = "radixtree_sni"
ssl = "radixtree_sni",
router_rebuild_min_interval = 0,
},
proxy_mode = "http",
resolver_timeout = 5,
Expand Down
14 changes: 14 additions & 0 deletions apisix/http/router/radixtree_host_uri.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ local core = require("apisix.core")
local event = require("apisix.core.event")
local get_services = require("apisix.http.service").services
local service_fetch = require("apisix.http.service").get
local ngx_now = ngx.now
local ipairs = ipairs
local type = type
local tab_insert = table.insert
local loadstring = loadstring
local pairs = pairs
local cached_router_version
local cached_service_version
local last_router_rebuild_time
local host_router
local only_uri_router

Expand Down Expand Up @@ -148,11 +150,23 @@ function _M.match(api_ctx)
if not cached_router_version or cached_router_version ~= user_routes.conf_version
or not cached_service_version or cached_service_version ~= service_version
then
local min_interval = _M.router_rebuild_min_interval or 0
if min_interval > 0 and last_router_rebuild_time then
local elapsed = ngx_now() - last_router_rebuild_time
if elapsed < min_interval then
core.log.info("skip router rebuild, elapsed: ", elapsed,
"s, min_interval: ", min_interval, "s")
goto MATCH
end
end

create_radixtree_router(user_routes.values)
cached_router_version = user_routes.conf_version
cached_service_version = service_version
last_router_rebuild_time = ngx_now()
end

::MATCH::
return _M.matching(api_ctx)
end

Expand Down
14 changes: 14 additions & 0 deletions apisix/http/router/radixtree_uri.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ local require = require
local core = require("apisix.core")
local base_router = require("apisix.http.route")
local get_services = require("apisix.http.service").services
local ngx_now = ngx.now
local cached_router_version
local cached_service_version
local last_router_rebuild_time


local _M = {version = 0.2}
Expand All @@ -33,12 +35,24 @@ function _M.match(api_ctx)
if not cached_router_version or cached_router_version ~= user_routes.conf_version
or not cached_service_version or cached_service_version ~= service_version
then
local min_interval = _M.router_rebuild_min_interval or 0
if min_interval > 0 and last_router_rebuild_time then
local elapsed = ngx_now() - last_router_rebuild_time
if elapsed < min_interval then
core.log.info("skip router rebuild, elapsed: ", elapsed,
"s, min_interval: ", min_interval, "s")
goto MATCH
end
end

uri_router = base_router.create_radixtree_uri_router(user_routes.values,
uri_routes, false)
cached_router_version = user_routes.conf_version
cached_service_version = service_version
last_router_rebuild_time = ngx_now()
end

::MATCH::
if not uri_router then
core.log.error("failed to fetch valid `uri` router: ")
return true
Expand Down
14 changes: 14 additions & 0 deletions apisix/http/router/radixtree_uri_with_parameter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ local require = require
local core = require("apisix.core")
local base_router = require("apisix.http.route")
local get_services = require("apisix.http.service").services
local ngx_now = ngx.now
local cached_router_version
local cached_service_version
local last_router_rebuild_time


local _M = {}
Expand All @@ -33,12 +35,24 @@ function _M.match(api_ctx)
if not cached_router_version or cached_router_version ~= user_routes.conf_version
or not cached_service_version or cached_service_version ~= service_version
then
local min_interval = _M.router_rebuild_min_interval or 0
if min_interval > 0 and last_router_rebuild_time then
local elapsed = ngx_now() - last_router_rebuild_time
if elapsed < min_interval then
core.log.info("skip router rebuild, elapsed: ", elapsed,
"s, min_interval: ", min_interval, "s")
goto MATCH
end
end

uri_router = base_router.create_radixtree_uri_router(user_routes.values,
uri_routes, true)
cached_router_version = user_routes.conf_version
cached_service_version = service_version
last_router_rebuild_time = ngx_now()
end

::MATCH::
if not uri_router then
core.log.error("failed to fetch valid `uri_with_parameter` router: ")
return true
Expand Down
12 changes: 12 additions & 0 deletions apisix/router.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local str_lower = string.lower
local ipairs = ipairs

local _M = {version = 0.3}
local router_rebuild_min_interval = 0


local function filter(route)
Expand Down Expand Up @@ -76,11 +77,14 @@ function _M.http_init_worker()
if conf and conf.apisix and conf.apisix.router then
router_http_name = conf.apisix.router.http or router_http_name
router_ssl_name = conf.apisix.router.ssl or router_ssl_name
router_rebuild_min_interval = conf.apisix.router.router_rebuild_min_interval
or router_rebuild_min_interval
end

local router_http = require("apisix.http.router." .. router_http_name)
attach_http_router_common_methods(router_http)
router_http.init_worker(filter)
router_http.router_rebuild_min_interval = router_rebuild_min_interval
_M.router_http = router_http

local router_ssl = require("apisix.ssl.router." .. router_ssl_name)
Expand All @@ -92,6 +96,7 @@ function _M.http_init_worker()
if conf and conf.apisix and conf.apisix.stream_proxy then
local router_stream = require("apisix.stream.router.ip_port")
router_stream.stream_init_worker(filter)
router_stream.router_rebuild_min_interval = router_rebuild_min_interval
_M.router_stream = router_stream
end

Expand All @@ -100,10 +105,17 @@ end


function _M.stream_init_worker()
local conf = core.config.local_conf()
local router_ssl_name = "radixtree_sni"
local min_interval = 0

if conf and conf.apisix and conf.apisix.router then
min_interval = conf.apisix.router.router_rebuild_min_interval or 0
end

local router_stream = require("apisix.stream.router.ip_port")
router_stream.stream_init_worker(filter)
router_stream.router_rebuild_min_interval = min_interval
_M.router_stream = router_stream

local router_ssl = require("apisix.ssl.router." .. router_ssl_name)
Expand Down
15 changes: 15 additions & 0 deletions apisix/stream/router/ip_port.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ local stream_plugin_checker = require("apisix.plugin").stream_plugin_checker
local router_new = require("apisix.utils.router").new
local apisix_ssl = require("apisix.ssl")
local xrpc = require("apisix.stream.xrpc")
local ngx_now = ngx.now
local error = error
local tonumber = tonumber
local ipairs = ipairs

local user_routes
local router_ver
local last_router_rebuild_time
local tls_router
local other_routes = {}
local _M = {version = 0.1}
Expand Down Expand Up @@ -144,14 +146,27 @@ do

function _M.match(api_ctx)
if router_ver ~= user_routes.conf_version then
local min_interval = _M.router_rebuild_min_interval or 0
if min_interval > 0 and last_router_rebuild_time then
local elapsed = ngx_now() - last_router_rebuild_time
if elapsed < min_interval then
core.log.info("skip stream router rebuild, elapsed: ", elapsed,
"s, min_interval: ", min_interval, "s")
goto MATCH
end
end

local err = create_router(user_routes.values)
if err then
return false, "failed to create router: " .. err
end

router_ver = user_routes.conf_version
last_router_rebuild_time = ngx_now()
end

::MATCH::

local sni = apisix_ssl.server_name()
if sni and tls_router then
local sni_rev = sni:reverse()
Expand Down
6 changes: 6 additions & 0 deletions conf/config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ apisix:
# radixtree_uri: match route by URI
# radixtree_uri_with_parameter: similar to radixtree_uri but match URI with parameters. See https://github.com/api7/lua-resty-radixtree/#parameters-in-path for more details.
ssl: radixtree_sni # radixtree_sni: match route by SNI
# router_rebuild_min_interval: 0 # Minimum interval (in seconds) between router rebuilds.
# When routes change frequently, the router is rebuilt on every
# change which can cause CPU spikes under high-frequency updates.
# Set this to a positive value (e.g. 1 or 5) to limit the
# rebuild frequency. Default 0 means rebuild immediately on
# every change (current behavior).

# http is the default proxy mode. proxy_mode can be one of `http`, `stream`, or `http&stream`
proxy_mode: "http"
Expand Down
Loading
Loading