This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 4cf30bf  refactor: keep health checker with the upstream's parent 
(#3325)
4cf30bf is described below

commit 4cf30bf2ac79d766355b89067e5e728bb02f232f
Author: 罗泽轩 <spacewander...@gmail.com>
AuthorDate: Mon Jan 18 08:21:39 2021 -0600

    refactor: keep health checker with the upstream's parent (#3325)
    
    A upstream's parent can only have one running checker.
    Previously, when a checker is evicted by lrucache, it is still running.
    Now health checker & upstream in used is 1:1.
---
 apisix/core.lua                | 39 ++++++++++++++++++-----------------
 apisix/core/config_util.lua    | 23 +++++++++++++++++++++
 apisix/upstream.lua            | 46 ++++++++++++++++++++++++------------------
 t/node/healthcheck-discovery.t |  5 +++--
 4 files changed, 72 insertions(+), 41 deletions(-)

diff --git a/apisix/core.lua b/apisix/core.lua
index f9432e0..f994de9 100644
--- a/apisix/core.lua
+++ b/apisix/core.lua
@@ -29,23 +29,24 @@ config.type = config_center
 
 
 return {
-    version  = require("apisix.core.version"),
-    log      = log,
-    config   = config,
-    sleep    = utils.sleep,
-    json     = require("apisix.core.json"),
-    table    = require("apisix.core.table"),
-    request  = require("apisix.core.request"),
-    response = require("apisix.core.response"),
-    lrucache = require("apisix.core.lrucache"),
-    schema   = require("apisix.schema_def"),
-    string   = require("apisix.core.string"),
-    ctx      = require("apisix.core.ctx"),
-    timer    = require("apisix.core.timer"),
-    id       = require("apisix.core.id"),
-    utils    = utils,
-    etcd     = require("apisix.core.etcd"),
-    http     = require("apisix.core.http"),
-    tablepool= require("tablepool"),
-    empty_tab= {},
+    version     = require("apisix.core.version"),
+    log         = log,
+    config      = config,
+    config_util = require("apisix.core.config_util"),
+    sleep       = utils.sleep,
+    json        = require("apisix.core.json"),
+    table       = require("apisix.core.table"),
+    request     = require("apisix.core.request"),
+    response    = require("apisix.core.response"),
+    lrucache    = require("apisix.core.lrucache"),
+    schema      = require("apisix.schema_def"),
+    string      = require("apisix.core.string"),
+    ctx         = require("apisix.core.ctx"),
+    timer       = require("apisix.core.timer"),
+    id          = require("apisix.core.id"),
+    utils       = utils,
+    etcd        = require("apisix.core.etcd"),
+    http        = require("apisix.core.http"),
+    tablepool   = require("tablepool"),
+    empty_tab   = {},
 }
diff --git a/apisix/core/config_util.lua b/apisix/core/config_util.lua
index 1e39921..cc29ea4 100644
--- a/apisix/core/config_util.lua
+++ b/apisix/core/config_util.lua
@@ -14,6 +14,7 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
+local core_tab = require("apisix.core.table")
 local setmetatable = setmetatable
 local type = type
 
@@ -42,4 +43,26 @@ function _M.iterate_values(tab)
 end
 
 
+-- Add a clean handler to a runtime configuration item.
+-- The clean handler will be called when the item is deleted from configuration
+-- or cancelled. Note that Nginx worker exit doesn't trigger the clean handler.
+-- Retuen an index so that we can cancel it later.
+function _M.add_clean_handler(item, func)
+    local idx = #item.clean_handlers + 1
+    item.clean_handlers[idx] = func
+    return idx
+end
+
+
+-- cancel a clean handler added by add_clean_handler.
+-- If `fire` is true, call the clean handler.
+function _M.cancel_clean_handler(item, idx, fire)
+    local f = item.clean_handlers[idx]
+    core_tab.remove(item.clean_handlers, idx)
+    if fire then
+        f(item)
+    end
+end
+
+
 return _M
diff --git a/apisix/upstream.lua b/apisix/upstream.lua
index ecd99bf..da19e45 100644
--- a/apisix/upstream.lua
+++ b/apisix/upstream.lua
@@ -26,11 +26,6 @@ local upstreams
 local healthcheck
 
 
-local lrucache_checker = core.lrucache.new({
-    ttl = 300, count = 256
-})
-
-
 local _M = {}
 
 
@@ -57,12 +52,24 @@ end
 _M.set = set_directly
 
 
+local function release_checker(healthcheck_parent)
+    local checker = healthcheck_parent.checker
+    core.log.info("try to release checker: ", tostring(checker))
+    checker:clear()
+    checker:stop()
+end
+
+
 local function create_checker(upstream)
     if healthcheck == nil then
         healthcheck = require("resty.healthcheck")
     end
 
     local healthcheck_parent = upstream.parent
+    if healthcheck_parent.checker and healthcheck_parent.checker_upstream == 
upstream then
+        return healthcheck_parent.checker
+    end
+
     local checker, err = healthcheck.new({
         name = "upstream#" .. healthcheck_parent.key,
         shm_name = "upstream-healthcheck",
@@ -84,29 +91,28 @@ local function create_checker(upstream)
         end
     end
 
-    core.table.insert(healthcheck_parent.clean_handlers, function ()
-        core.log.info("try to release checker: ", tostring(checker))
-        checker:clear()
-        checker:stop()
-    end)
+    if healthcheck_parent.checker then
+        core.config_util.cancel_clean_handler(healthcheck_parent,
+                                              healthcheck_parent.checker_idx, 
true)
+    end
 
     core.log.info("create new checker: ", tostring(checker))
+
+    healthcheck_parent.checker = checker
+    healthcheck_parent.checker_upstream = upstream
+    healthcheck_parent.checker_idx =
+        core.config_util.add_clean_handler(healthcheck_parent, release_checker)
+
     return checker
 end
 
 
-local function fetch_healthchecker(upstream, version)
+local function fetch_healthchecker(upstream)
     if not upstream.checks then
-        return
-    end
-
-    if upstream.checker then
-        return
+        return nil
     end
 
-    local checker = lrucache_checker(upstream, version,
-                                     create_checker, upstream)
-    return checker
+    return create_checker(upstream)
 end
 
 
@@ -164,7 +170,7 @@ function _M.set_by_route(route, api_ctx)
     end
 
     if nodes_count > 1 then
-        local checker = fetch_healthchecker(up_conf, api_ctx.upstream_version)
+        local checker = fetch_healthchecker(up_conf)
         api_ctx.up_checker = checker
     end
 
diff --git a/t/node/healthcheck-discovery.t b/t/node/healthcheck-discovery.t
index 6123fff..41c490e 100644
--- a/t/node/healthcheck-discovery.t
+++ b/t/node/healthcheck-discovery.t
@@ -151,9 +151,10 @@ routes:
         }
     }
 --- grep_error_log eval
-qr/create new checker: table/
+qr/(create new checker|try to release checker): table/
 --- grep_error_log_out
 create new checker: table
+try to release checker: table
 create new checker: table
 
 
@@ -198,6 +199,6 @@ routes:
         }
     }
 --- grep_error_log eval
-qr/create new checker: table/
+qr/(create new checker|try to release checker): table/
 --- grep_error_log_out
 create new checker: table

Reply via email to