【网关开发】6.lua绑定委托(delegate)实现多播调用
1.【网关开发】1.编译Openresty 服务器初始化搭建2.【网关开发】2.Openresty 使用lua扩展 链接etcd数据库
3.【网关开发】6.lua绑定委托(delegate)实现多播调用
4.【网关开发】5.Openresty 自定义负载均衡与流量转发5.【网关开发】4.Openresty 使用events插件进行事件通知6.【网关开发】3.Openresty lua使用lmdb数据库7.【网关开发】10.Openresty 网关全链路的数据生成与数据上报8.【网关开发】9.Openresty 自定义流量分流策略支持灰度(金丝雀)等发布业务场景9.【网关开发】8.Openresty 网关自定义健康检查的设计与实现10.【网关开发】7.Openresty使用cosocket API 发送http与tcp网络请求背景
在程序开发过程中有时会遇到事件流的问题,某一个结果会触发A、B、C等一系列动作。需要将各种事件注册给委托类(Delegate)。Delegate类会依次触发注册的函数,完成相应的动作。
实现原理
lua中可以使用元表和队列的形式进行实现
实现细节
delegate.lua
local _M = { }
local _MT = { __index = _M }
local setmetatable = setmetatable
local table_remove = table.remove
-- _invoke_list 注册队列
-- _count 注册计数
function _M.new()
return setmetatable({ _invoke_list = { }, _count = 0 }, _MT)
end
-- __call 函数实现
function _MT:__call(...)
local _invoke_list = self._invoke_list
for i = 1, self._count do
_invoke_list[i](...)
end
end
-- 增加
local function add_delegate(self, cb, ...)
if not cb then
return self
end
local _invoke_list = self._invoke_list
local idx = self._count + 1
self._invoke_list[idx] = cb
self._count = idx
return add_delegate(self, ...) -- 递归添加
end
-- 会检查是否已经注册
local function add_delegate2(self, cb, ...)
if not cb then
return self
end
local _invoke_list = self._invoke_list
for i = 1, self._count do
if _invoke_list[i] == cb then
-- already exists, skip
return add_delegate2(self, ...)
end
end
local _invoke_list = self._invoke_list
local idx = self._count + 1
self._invoke_list[idx] = cb
self._count = idx
return add_delegate2(self, ...)
end
local function remove_delegate(self, cb, ...)
if not cb then
return self
end
local _invoke_list = self._invoke_list
for i = 1, self._count do
if _invoke_list[i] == cb then
table_remove(_invoke_list, i)
self._count = self._count - 1
break
end
end
return remove_delegate(self, ...)
end
local function is_empty(self)
return self._count == 0
end
_M.__add = add_delegate
_M.__sub = remove_delegate
_M.invoke = _MT.__call
_M.add_delegate = add_delegate
_M.add_delegate2 = add_delegate2
_M.remove_delegate = remove_delegate
_M.is_empty = is_empty
return _M
应用
-- 测试函数
local function delegate_test1(data)
ngx.log(ngx.INFO,"delegate_test1 "..data)
end
local function delegate_test2(data)
ngx.log(ngx.INFO,"delegate_test2 ".. data)
end
local function init()
watcher = delegate.new()
watcher:add_delegate2(delegate_test1)
watcher:add_delegate2(delegate_test2)
watcher("test")
end
测试
思考与总结
整个实现就是一个简单列表和对列表的操作,很好理解。结合场景实现一些广播功会更加方便。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?