coder2z commented on code in PR #12261:
URL: https://github.com/apache/apisix/pull/12261#discussion_r2533018058


##########
apisix/balancer/least_conn.lua:
##########
@@ -17,33 +17,146 @@
 
 local core = require("apisix.core")
 local binaryHeap = require("binaryheap")
+local dkjson = require("dkjson")
 local ipairs = ipairs
 local pairs = pairs
-
+local ngx = ngx
+local ngx_shared = ngx.shared
+local tostring = tostring
 
 local _M = {}
 
+-- Shared dictionary to store connection counts across balancer recreations
+local CONN_COUNT_DICT_NAME = "balancer-least-conn"
+local conn_count_dict
 
 local function least_score(a, b)
     return a.score < b.score
 end
 
+-- Get the connection count key for a specific upstream and server
+local function get_conn_count_key(upstream, server)
+    local upstream_id = upstream.id
+    if not upstream_id then
+        -- Fallback to a hash of the upstream configuration using stable 
encoding
+        upstream_id = ngx.crc32_short(dkjson.encode(upstream))
+        core.log.debug("generated upstream_id from hash: ", upstream_id)
+    end
+    local key = "conn_count:" .. tostring(upstream_id) .. ":" .. server
+    core.log.debug("generated connection count key: ", key)
+    return key
+end
+
+-- Get the current connection count for a server from shared dict
+local function get_server_conn_count(upstream, server)
+    local key = get_conn_count_key(upstream, server)
+    local count, err = conn_count_dict:get(key)
+    if err then
+        core.log.error("failed to get connection count for ", server, ": ", 
err)
+        return 0
+    end
+    local result = count or 0
+    core.log.debug("retrieved connection count for server ", server, ": ", 
result)
+    return result
+end
+
+-- Increment the connection count for a server
+local function incr_server_conn_count(upstream, server, delta)
+    local key = get_conn_count_key(upstream, server)
+    local new_count, err = conn_count_dict:incr(key, delta or 1, 0)
+    if not new_count then
+        core.log.error("failed to increment connection count for ", server, ": 
", err)
+        return 0
+    end
+    core.log.debug("incremented connection count for server ", server, " by ", 
delta or 1,
+            ", new count: ", new_count)
+    return new_count
+end
+
+-- Clean up connection counts for servers that are no longer in the upstream
+local function cleanup_stale_conn_counts(upstream, current_servers)
+    local upstream_id = upstream.id
+    if not upstream_id then
+        upstream_id = ngx.crc32_short(dkjson.encode(upstream))
+    end
+
+    local prefix = "conn_count:" .. tostring(upstream_id) .. ":"
+    core.log.debug("cleaning up stale connection counts with prefix: ", prefix)
+    local keys, err = conn_count_dict:get_keys(0)  -- Get all keys
+    if err then
+        core.log.error("failed to get keys from shared dict: ", err)
+        return
+    end
+
+    for _, key in ipairs(keys or {}) do
+        if core.string.has_prefix(key, prefix) then
+            local server = key:sub(#prefix + 1)
+            if not current_servers[server] then
+                -- This server is no longer in the upstream, clean it up
+                local ok, delete_err = conn_count_dict:delete(key)
+                if not ok and delete_err then
+                    core.log.error("failed to delete stale connection count 
for server ",
+                            server, ": ", delete_err)
+                else
+                    core.log.info("cleaned up stale connection count for 
server: ", server)
+                end
+            end
+        end
+    end
+end
 
 function _M.new(up_nodes, upstream)
+    if not conn_count_dict then
+        conn_count_dict = ngx_shared[CONN_COUNT_DICT_NAME]
+    end
+
+    -- Enable persistent counting only when explicitly requested
+    -- This ensures complete backward compatibility with existing behavior
+    local use_persistent_counting = conn_count_dict ~= nil and
+        upstream.persistent_conn_counting == true

Review Comment:
   If it is the standalone method, it is the simplest, directly modify the 
upstream configuration item, and if it is the UI mode, you need to modify the 
corresponding route and UI.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to