diff --git a/api/router/tl_ops_api_get_state.lua b/api/router/tl_ops_api_get_state.lua index c34c227..37608e6 100644 --- a/api/router/tl_ops_api_get_state.lua +++ b/api/router/tl_ops_api_get_state.lua @@ -119,6 +119,7 @@ local Router = function() local limit_rate local limit_pre_time local limit_bucket + local limit_block if limit_depend == tl_ops_constant_limit.depend.token then limit_capacity = shared:get(tl_ops_utils_func:gen_node_key(tl_ops_constant_limit.token.cache_key.capacity, node.service, node_id)) if not limit_capacity then @@ -128,6 +129,10 @@ local Router = function() if not limit_rate then limit_rate = 'nil' end + limit_block = shared:get(tl_ops_utils_func:gen_node_key(tl_ops_constant_limit.token.cache_key.block, node.service, node_id)) + if not limit_block then + limit_block = 'nil' + end limit_pre_time = shared:get(tl_ops_utils_func:gen_node_key(tl_ops_constant_limit.token.cache_key.pre_time, node.service, node_id)) if not limit_pre_time then limit_pre_time = 'nil' @@ -137,6 +142,7 @@ local Router = function() limit_bucket = 'nil' end end + if limit_depend == tl_ops_constant_limit.depend.leak then limit_capacity = shared:get(tl_ops_utils_func:gen_node_key(tl_ops_constant_limit.leak.cache_key.capacity, node.service, node_id)) if not limit_capacity then @@ -146,6 +152,10 @@ local Router = function() if not limit_rate then limit_rate = 'nil' end + limit_block = shared:get(tl_ops_utils_func:gen_node_key(tl_ops_constant_limit.leak.cache_key.block, node.service, node_id)) + if not limit_block then + limit_block = 'nil' + end limit_pre_time = shared:get(tl_ops_utils_func:gen_node_key(tl_ops_constant_limit.leak.cache_key.pre_time, node.service, node_id)) if not limit_pre_time then limit_pre_time = 'nil' @@ -173,6 +183,7 @@ local Router = function() limit_depend = limit_depend, limit_capacity = limit_capacity, limit_rate = limit_rate, + limit_block = limit_block, limit_pre_time = limit_pre_time, limit_bucket = limit_bucket, balance_success = cjson.decode(balance_success_cache), diff --git a/constant/tl_ops_constant_limit.lua b/constant/tl_ops_constant_limit.lua index 6742283..1c7e663 100644 --- a/constant/tl_ops_constant_limit.lua +++ b/constant/tl_ops_constant_limit.lua @@ -6,6 +6,7 @@ local token = { --服务令牌桶配置 cache_key = { options_list = "tl_ops_limit_token_options_list", capacity = "tl_ops_limit_token_capacity_service", + block = "tl_ops_limit_token_block_service", rate = "tl_ops_limit_token_rate_service", expand = "tl_ops_limit_leak_expand_service", shrink = "tl_ops_limit_leak_shrink_service", @@ -33,6 +34,7 @@ local leak = { --服务漏桶配置 cache_key = { options_list = "tl_ops_limit_leak_options_list", capacity = "tl_ops_limit_leak_capacity_service", + block = "tl_ops_limit_leak_block_service", rate = "tl_ops_limit_leak_rate_service", expand = "tl_ops_limit_leak_expand_service", shrink = "tl_ops_limit_leak_shrink_service", @@ -53,10 +55,41 @@ local leak = { --服务漏桶配置 } } +-- 滑动窗口配置 +local sliding = { --服务滑动窗口配置 + cache_key = { + options_list = "tl_ops_limit_sliding_options_list", + window = "tl_ops_limit_sliding_window_service", + block = "tl_ops_limit_sliding_block_service", + cycle = "tl_ops_limit_sliding_cycle_service", + limit = "tl_ops_limit_sliding_limit_service", + rate = "tl_ops_limit_sliding_rate_service", + expand = "tl_ops_limit_sliding_expand_service", + shrink = "tl_ops_limit_sliding_shrink_service", + count = "tl_ops_limit_sliding_count_service", + pre_time = "tl_ops_limit_sliding_pre_time_service", + lock = "tl_ops_limit_sliding_lock_service" + }, + options = { + + }, + demo = { + service_name = "tlops-demo", -- 滑动窗口配置所属服务 + window = 60, -- 滑动窗口大小,理解为时间窗口(单位秒,默认一个窗口60s) + limit = 1024 * 100, -- 滑动窗口限制请求的数量 (默认时间窗口60s,限制请求100 * 单位个) + cycle = 10, -- 区间个数 (默认时间窗口60s,切分为10个,每个区间6s) + rate = 1, -- 窗口一次滑动多少个区间 + block = 1024, -- 请求单位 (按字节为单位,可做字节整型流控) + expand = 0.5, -- 扩容比例 + shrink = 0.5, -- 缩容比例 + } +} + -- 依赖限流组件 local depend = { token = "token", - leak = "leak" + leak = "leak", + sliding = "sliding" } -- 组件级别 @@ -104,6 +137,7 @@ local tl_ops_constant_limit = { fuse = fuse, token = token, leak = leak, + sliding = sliding, depend = depend, level = level, mode = mode diff --git a/doc/change.md b/doc/change.md index 992e91c..69fc701 100644 --- a/doc/change.md +++ b/doc/change.md @@ -1,6 +1,19 @@ ## 事务更新日程 +2022-12-21 + + 1. 支持滑动窗口算法 + + 2. 优化健康检查逻辑 + + 3. 修复限流block不生效 + + 4. 补充文档 + + 5. 事务日程调整 + + 2022-09-15 1. 支持登录插件配置实时修改 diff --git a/gitbook/usage/intro/README.md b/gitbook/usage/intro/README.md index d81e9cb..7227ed1 100644 --- a/gitbook/usage/intro/README.md +++ b/gitbook/usage/intro/README.md @@ -4,3 +4,14 @@ tl-ops-manage (tl-openresty-web-manage),基于openresty开发的一款基 做这个项目最开始的想法很简单,只是想在造轮子的过程中了解,学习一些新的知识面。到后面完成了大部分基础功能点后,发现可以整理为一个服务管理工具的项目。于是就有了tl-ops-manage。 + +## 优势 + +### 代码简洁,通俗易懂,没有特殊复杂逻辑交互,十分清晰明了的执行流程,和详细的模块说明文档。 + +### 项目许多模块和算法都是可独立出来作基础组件。 + +### 配置环境,操作界面,容易上手,无需依赖过多第三方环境。 + +### 容易扩展,适合个人,中小企业贴合业务扩展具体场景逻辑。 + diff --git a/health/tl_ops_health_check.lua b/health/tl_ops_health_check.lua index 60d3fc7..79f4aa9 100644 --- a/health/tl_ops_health_check.lua +++ b/health/tl_ops_health_check.lua @@ -4,18 +4,16 @@ -- @author iamtsm -- @email 1905333456@qq.com -local cjson = require("cjson.safe") -local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_health") -local tl_ops_utils_func = require("utils.tl_ops_utils_func") -local tl_ops_constant_health = require("constant.tl_ops_constant_health") -local tl_ops_status = require("constant.tl_ops_constant_comm").tl_ops_status; -local tl_ops_health_check_dynamic_conf = require("health.tl_ops_health_check_dynamic_conf") -local tl_ops_health_check_version = require("health.tl_ops_health_check_version") -local nx_socket = ngx.socket.tcp -local shared = ngx.shared.tlopsbalance -local find = ngx.re.find - - +local cjson = require("cjson.safe") +local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_health") +local tl_ops_utils_func = require("utils.tl_ops_utils_func") +local tl_ops_constant_health = require("constant.tl_ops_constant_health") +local tl_ops_status = require("constant.tl_ops_constant_comm").tl_ops_status; +local tl_ops_health_check_dynamic_conf = require("health.tl_ops_health_check_dynamic_conf") +local tl_ops_health_check_version = require("health.tl_ops_health_check_version") +local nx_socket = ngx.socket.tcp +local shared = ngx.shared.tlopsbalance +local find = ngx.re.find local _M = { _VERSION = '0.02' @@ -238,6 +236,7 @@ tl_ops_health_check_nodes = function (conf) local bytes, _ = sock:send(check_content .. "\r\n\r\n\r\n") if not bytes then tlog:err("tl_ops_health_check_nodes failed to send socket: ", _) + socket:close() tl_ops_health_check_node_failed(conf, node_id, node) break end @@ -245,19 +244,21 @@ tl_ops_health_check_nodes = function (conf) tlog:dbg("tl_ops_health_check_nodes send socket ok : byte=", bytes) -- socket反馈 - local receive_line, _ = sock:receive() - if not receive_line then + local receive_10k, _ = sock:receiveany(10240) + if not receive_10k then if _ == "check_timeout" then tlog:err("tl_ops_health_check_nodes socket check_timeout: ", _) - sock:close() end + + tlog:err("tl_ops_health_check_nodes socket receive failed: ", receive_10k) + sock:close() tl_ops_health_check_node_failed(conf, node_id, node) break end - tlog:dbg("tl_ops_health_check_nodes receive socket ok : ", receive_line) + tlog:dbg("tl_ops_health_check_nodes receive socket ok : ", receive_10k) - local from, to, _ = find(receive_line, [[^HTTP/\d+\.\d+\s+(\d+)]], "joi", nil, 1) + local from, to, _ = find(receive_10k, [[^HTTP/\d+\.\d+\s+(\d+)]], "joi", nil, 1) if not from then tlog:err("tl_ops_health_check_nodes ngx.re.find receive err: ", from, to, _) sock:close() @@ -266,7 +267,7 @@ tl_ops_health_check_nodes = function (conf) end -- 心跳状态 - local status = tonumber(string.sub(receive_line, from, to)) + local status = tonumber(string.sub(receive_10k, from, to)) tlog:dbg("tl_ops_health_check_nodes get status ok ,name=" ,name, ", status=" , status) local statusPass = false; diff --git a/health/tl_ops_health_check_dynamic_conf.lua b/health/tl_ops_health_check_dynamic_conf.lua index 48870c8..90d4ebe 100644 --- a/health/tl_ops_health_check_dynamic_conf.lua +++ b/health/tl_ops_health_check_dynamic_conf.lua @@ -5,13 +5,13 @@ -- @email 1905333456@qq.com -local cjson = require("cjson.safe"); -local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_health_check_dynamic_conf"); -local tl_ops_utils_func = require("utils.tl_ops_utils_func"); -local tl_ops_constant_health = require("constant.tl_ops_constant_health") -local cache_health = require("cache.tl_ops_cache_core"):new("tl-ops-health"); -local tl_ops_constant_service = require("constant.tl_ops_constant_service"); -local shared = ngx.shared.tlopsbalance +local cjson = require("cjson.safe"); +local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_health_check_dynamic_conf"); +local tl_ops_utils_func = require("utils.tl_ops_utils_func"); +local tl_ops_constant_health = require("constant.tl_ops_constant_health") +local cache_health = require("cache.tl_ops_cache_core"):new("tl-ops-health"); +local tl_ops_constant_service = require("constant.tl_ops_constant_service"); +local shared = ngx.shared.tlopsbalance -- 需要提前定义,定时器访问不了 local tl_ops_health_check_dynamic_conf_add_timer_check; diff --git a/limit/fuse/tl_ops_limit_fuse_check.lua b/limit/fuse/tl_ops_limit_fuse_check.lua index 2bb9ae9..67201e8 100644 --- a/limit/fuse/tl_ops_limit_fuse_check.lua +++ b/limit/fuse/tl_ops_limit_fuse_check.lua @@ -4,17 +4,17 @@ -- @author iamtsm -- @email 1905333456@qq.com -local tl_ops_utils_func = require("utils.tl_ops_utils_func"); +local tl_ops_utils_func = require("utils.tl_ops_utils_func"); local tl_ops_limit_fuse_check_dynamic_conf = require("limit.fuse.tl_ops_limit_fuse_check_dynamic_conf") -local tl_ops_limit_fuse_check_version = require("limit.fuse.tl_ops_limit_fuse_check_version") -local tl_ops_limit_token_bucket = require("limit.fuse.tl_ops_limit_fuse_token_bucket"); -local tl_ops_limit_leak_bucket = require("limit.fuse.tl_ops_limit_fuse_leak_bucket"); -local tl_ops_constant_limit = require("constant.tl_ops_constant_limit") -local tl_ops_constant_health = require("constant.tl_ops_constant_health") -local tl_ops_constant_service = require("constant.tl_ops_constant_service") -local shared = ngx.shared.tlopsbalance -local cjson = require("cjson.safe"); -local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_limit_fuse"); +local tl_ops_limit_fuse_check_version = require("limit.fuse.tl_ops_limit_fuse_check_version") +local tl_ops_limit_token_bucket = require("limit.fuse.tl_ops_limit_fuse_token_bucket"); +local tl_ops_limit_leak_bucket = require("limit.fuse.tl_ops_limit_fuse_leak_bucket"); +local tl_ops_constant_limit = require("constant.tl_ops_constant_limit") +local tl_ops_constant_health = require("constant.tl_ops_constant_health") +local tl_ops_constant_service = require("constant.tl_ops_constant_service") +local shared = ngx.shared.tlopsbalance +local cjson = require("cjson.safe"); +local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_limit_fuse"); local _STATE = { diff --git a/limit/fuse/tl_ops_limit_fuse_check_dynamic_conf.lua b/limit/fuse/tl_ops_limit_fuse_check_dynamic_conf.lua index 2e97947..d913716 100644 --- a/limit/fuse/tl_ops_limit_fuse_check_dynamic_conf.lua +++ b/limit/fuse/tl_ops_limit_fuse_check_dynamic_conf.lua @@ -4,13 +4,13 @@ -- @author iamtsm -- @email 1905333456@qq.com -local cjson = require("cjson.safe"); -local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_limit_fuse_check_dynamic_conf"); -local tl_ops_utils_func = require("utils.tl_ops_utils_func"); -local tl_ops_constant_limit = require("constant.tl_ops_constant_limit") -local cache_limit = require("cache.tl_ops_cache_core"):new("tl-ops-limit"); +local cjson = require("cjson.safe"); +local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_limit_fuse_check_dynamic_conf"); +local tl_ops_utils_func = require("utils.tl_ops_utils_func"); +local tl_ops_constant_limit = require("constant.tl_ops_constant_limit") +local cache_limit = require("cache.tl_ops_cache_core"):new("tl-ops-limit"); local tl_ops_constant_service = require("constant.tl_ops_constant_service") -local shared = ngx.shared.tlopsbalance +local shared = ngx.shared.tlopsbalance local tl_ops_limit_fuse_check_dynamic_conf_add_timer_check; diff --git a/limit/fuse/tl_ops_limit_fuse_leak_bucket.lua b/limit/fuse/tl_ops_limit_fuse_leak_bucket.lua index d55e02d..1f162b8 100644 --- a/limit/fuse/tl_ops_limit_fuse_leak_bucket.lua +++ b/limit/fuse/tl_ops_limit_fuse_leak_bucket.lua @@ -61,7 +61,15 @@ end local tl_ops_limit_leak = function( service_name, node_id ) local leak_mode = tl_ops_limit_leak_mode( service_name , node_id) - local block = leak_mode.options.block + local block_key = tl_ops_utils_func:gen_node_key(leak_mode.cache_key.block, service_name, node_id) + local block = shared:get(block_key) + if not block then + local res, _ = shared:set(block, leak_mode.options.block) + if not res then + return false + end + block = leak_mode.options.block + end local capacity_key = tl_ops_utils_func:gen_node_key(leak_mode.cache_key.capacity, service_name, node_id) local capacity = shared:get(capacity_key) @@ -176,7 +184,15 @@ local tl_ops_limit_leak_shrink = function( service_name, node_id ) local leak_mode = tl_ops_limit_leak_mode( service_name, node_id) - local block = leak_mode.options.block + local block_key = tl_ops_utils_func:gen_node_key(leak_mode.cache_key.block, service_name, node_id) + local block = shared:get(block_key) + if not block then + local res, _ = shared:set(block, leak_mode.options.block) + if not res then + return false + end + block = leak_mode.options.block + end local capacity_key = tl_ops_utils_func:gen_node_key(leak_mode.cache_key.capacity, service_name, node_id) local capacity = shared:get(capacity_key) diff --git a/limit/fuse/tl_ops_limit_fuse_token_bucket.lua b/limit/fuse/tl_ops_limit_fuse_token_bucket.lua index d8fd5b0..316ecce 100644 --- a/limit/fuse/tl_ops_limit_fuse_token_bucket.lua +++ b/limit/fuse/tl_ops_limit_fuse_token_bucket.lua @@ -61,8 +61,6 @@ end local tl_ops_limit_token = function( service_name, node_id ) local token_mode = tl_ops_limit_token_mode( service_name , node_id) - local block = token_mode.options.block - local capacity_key = tl_ops_utils_func:gen_node_key(token_mode.cache_key.capacity, service_name, node_id) local capacity = shared:get(capacity_key) if not capacity then @@ -104,6 +102,16 @@ local tl_ops_limit_token = function( service_name, node_id ) token_bucket = 0 end + local block_key = tl_ops_utils_func:gen_node_key(token_mode.cache_key.block, service_name, node_id) + local block = shared:get(block_key) + if not block then + local res, _ = shared:set(block_key, token_mode.options.block) + if not res then + return false + end + block = token_mode.options.block + end + -- 取出令牌 if token_bucket > block then local ok, _ = shared:incr(token_bucket_key, -block) @@ -198,8 +206,6 @@ end local tl_ops_limit_token_shrink = function( service_name, node_id ) local token_mode = tl_ops_limit_token_mode( service_name, node_id) - - local block = token_mode.options.block local capacity_key = tl_ops_utils_func:gen_node_key(token_mode.cache_key.capacity, service_name, node_id) local capacity = shared:get(capacity_key) @@ -211,6 +217,16 @@ local tl_ops_limit_token_shrink = function( service_name, node_id ) capacity = token_mode.options.capacity end + local block_key = tl_ops_utils_func:gen_node_key(token_mode.cache_key.block, service_name, node_id) + local block = shared:get(block_key) + if not block then + local res, _ = shared:set(block_key, token_mode.options.block) + if not res then + return false + end + block = token_mode.options.block + end + -- 无需缩容 if capacity <= block then return true diff --git a/limit/tl_ops_limit_sliding_window.lua b/limit/tl_ops_limit_sliding_window.lua index aa4ce13..ac5a1af 100644 --- a/limit/tl_ops_limit_sliding_window.lua +++ b/limit/tl_ops_limit_sliding_window.lua @@ -8,7 +8,7 @@ local cjson = require("cjson.safe"); local tlog = require("utils.tl_ops_utils_log"):new("tl_ops_limit_sliding_window"); local tl_ops_utils_func = require("utils.tl_ops_utils_func"); - +local shared = ngx.shared.tlopsbalance local _M = { _VERSION = '0.02' @@ -17,21 +17,269 @@ local mt = { __index = _M } -function _M:new( options ) - return setmetatable({options = options}, mt) +function _M:new( options, keys ) + if not options or options == nil or not keys or keys == nil then + tlog:err(" options nil or keys nil") + return setmetatable({}, mt) + end + + local block = tonumber(options.block) + if not block or block <= 0 then + block = options.block + end + local ok, _ = shared:set(keys.block, block) + if not ok then + tlog:err(" init sliding window block err, block=",block,",err=",_) + return + end + + local limit = tonumber(options.limit) + if not limit or limit <= 0 then + limit = options.limit + end + local ok, _ = shared:set(keys.limit, limit) + if not ok then + tlog:err(" init sliding window limit err, limit=",limit,",err=",_) + return + end + + local expand = tonumber(options.expand) + if not expand or expand <= 0 then + expand = options.expand + end + local ok, _ = shared:set(keys.expand, expand) + if not ok then + tlog:err(" init sliding window expand err, expand=",expand,",err=",_) + return + end + + local shrink = tonumber(options.shrink) + if not shrink or shrink <= 0 then + shrink = options.shrink + end + local ok, _ = shared:set(keys.shrink, shrink) + if not ok then + tlog:err(" init sliding window shrink err, shrink=",shrink,",err=",_) + return + end + + local ok, _ = shared:set(keys.count, 0) + if not ok then + tlog:err(" init sliding window count err, count=",count,",err=",_) + return + end + + local final_option = { + block = block, + limit = limit, + } + tlog:dbg("new sliding window ok ,options=",final_option) + + return setmetatable({options = final_option, keys = keys}, mt) +end + + +-- try sliding, 尝试通过滑动窗口 +-- block : 请求大小 +local tl_ops_limit_sliding_window = function( block ) + + local window = shared:get(self.keys.window) + if not window then + return false + end + + local cycle = shared:get(self.keys.cycle) + if not cycle then + return false + end + + local pre_time, _ = shared:get(self.keys.pre_time) + if not pre_time then + return false + end + + ngx.update_time() + local cur_time = ngx.now() + local cur_duration = (cur_time - pre_time) / 1000 + + -- 每个区间的时间 = 滑动时间窗口大小 / 需要拆分的区间数量 + local cycle_time = math.floor(window / cycle) + + -- 当前时间所处的区间 等价于 需要滑动的区间个数 + local point = math.floor(cur_duration / cycle_time) + + -- 达到滑动时间 + if cur_duration >= cycle_time then + + -- 统计并清除过期区间 + local old_count = 0 + for i = 0, point do + local count, _ = shared:get(self.keys.count .. i) + if not count then + count = 0 + end + local res, _ = shared:del(self.keys.count .. i) + if not res then + return false + end + old_count = old_count + count + end + + -- 更新总量 + local ok, _ = shared:incr(self.keys.count, -old_count) + if not ok then + return false + end + + -- 最新时间窗口边界 = 上一次的时间窗口边界 + (point个区间 * 每个区间所占用的时间) + local new_time = pre_time + (point * (cycle_time * 1000)) + local ok, _ = shared:set(self.keys.pre_time, new_time) + if not ok then + return false + end + end + + -- 记录总量 + local ok, _ = shared:incr(self.keys.count, block) + if not ok then + return false + end + + -- 记录小区间 + local ok, _ = shared:incr(self.keys.count .. point, block) + if not ok then + return false + end + + -- 请求量是否超过窗口最大限制 + local count = shared:get(self.keys.count) + if not count then + return false + end + + local limit = shared:get(self.keys.limit) + if not limit then + return false + end + + if count >= limit then + return false + end + + return true end --- sliding init -function _M:init() +-- try sliding +function _M:tl_ops_sliding_window( block ) + if not block or type(block) ~= 'number' then + return false + end + + if block <= 0 then + return false + end + + -- lock + local lock, err = lock:new("tlopsbalance") + if not lock then + return false + end + local elapsed, err = lock:lock(self.keys.lock) + if not elapsed then + return false + end + local sliding = tl_ops_limit_sliding_window( block ) + if not sliding or sliding == false then + return false + end + + -- unlock + local ok, err = lock:unlock() + if not ok then + return false + end + + return true end +-- 扩容 +function _M:tl_pos_sliding_window_expand( ) + if self.options.block <= 0 then + return false + end + + -- 扩容量 = 当前窗口大小 * 比例 + local expand_block = self.options.block * self.options.expand --- sliding? -function _M:tl_ops_limit_sliding( ) + -- lock + local lock, err = lock:new("tlopsbalance") + if not lock then + return false + end + + local elapsed, err = lock:lock(self.keys.lock) + if not elapsed then + return false + end -end \ No newline at end of file + local res ,_ = shared:incr(self.keys.block, expand_block) + if not res or res == false then + return false + end + + self.options.block = self.options.block + expand_block + + -- unlock + local ok, err = lock:unlock() + if not ok then + return false + end + + return true +end + + +-- 缩容 +function _M:tl_pos_sliding_window_shrink( ) + if self.options.block <= 0 then + return false + end + + -- 缩容量 = -当前窗口大小 * 比例 + local shrink_block = self.options.block * self.options.shrink + + -- lock + local lock, err = lock:new("tlopsbalance") + if not lock then + return false + end + + local elapsed, err = lock:lock(self.keys.lock) + if not elapsed then + return false + end + + local res ,_ = shared:incr(self.keys.block, -shrink_block) + if not res or res == false then + return false + end + + self.options.block = self.options.block - shrink_block + + -- unlock + local ok, err = lock:unlock() + if not ok then + return false + end + + return true +end + + + +return _M \ No newline at end of file diff --git a/utils/tl_ops_utils_func.lua b/utils/tl_ops_utils_func.lua index 635e0f8..6e54d97 100644 --- a/utils/tl_ops_utils_func.lua +++ b/utils/tl_ops_utils_func.lua @@ -393,6 +393,41 @@ function _M:gen_node_key(prefix, node, node_id) end end +-- 替换func +function _M.replace(oldfunction, newfunction) + local visited = {} + local function f(t) + if not t or visited[t] then return end + visited[t] = true + if type(t) == "function" then + for i = 1, math.huge do + local name, value = debug.getupvalue(t, i) + + if not name then break end + f(value) + end + elseif type(t) == "table" then + f(debug.getmetatable(t)) + for k,v in pairs(t) do + f(k); f(v); + if type(v) == "function" or type(k) == "function" then + if v == oldfunction then t[k] = newfunction end + if k == oldfunction then + t[newfunction] = t[k] + t[k] = nil + end + end + end + end + end + f(_G) + local registryTable = debug.getregistry() + for k, v in pairs(registryTable) do + if v == oldfunction then + registryTable[k] = newfunction + end + end +end diff --git a/web/console/tl_ops_web_console.html b/web/console/tl_ops_web_console.html index ded6271..a83195f 100644 --- a/web/console/tl_ops_web_console.html +++ b/web/console/tl_ops_web_console.html @@ -58,6 +58,19 @@ #tl-console-load-sync .layui-form-switch{ margin-top: 0px; margin-right: 5px; + position: absolute; + right: 10px; + } + #tl-console-load-sync{ + text-align: right; + width: 100px; + position: absolute; + right: 12px; + height: 22px; + } + #tl-console-load-sync-icon{ + margin-right: -12px; + margin-top: 4px; } @@ -120,11 +133,11 @@
+ -
-
+