存在业务场景,从单点进程(source)批量向集群内其他节点(target)推送消息,目标节点数量可能达三位数。
提供一个实现方案:
- target上开启进程内的组播服务,只负责当前节点的组播推送业务;服务支持接收其他节点的通知消息(目标服务只在所在节点内的组播服务上做订阅等操作,由该组播服务负责管理);
- source进程构造组播消息包,做一次循环将消息发送到所有目标节点(这里只是寻常的remote send,multicast消息类型不是必须的,最常用的lua消息类型足够使用);
- target上的组播服务将数据包pack成multicast消息类型转发到所有目标订阅服务;
一段代码说明下:
-- source service
for _, skynet_node in ipairs(get_target_nodes()) do
cluster.send(skynet_node, "multicastd", "lua", "remote_publish", channel, msg)
end
-- multicastd
local subscribes = {
-- channel = {
-- service,
-- ...
-- },
-- ...
}
local MULTICAST_CMD = {
publish = function(channel, msg)
for service in pairs(subscribes[channel]) do
skynet.send(service, "multicast", msg)
end
end,
subscribe = function(...)
...
end,
newchannel = function(...)
...
end,
...
}
local LUA_CMD = {
remote_publish = function(...)
local channel, msg = unpack(...)
MULTICAST_CMD.publish(channel, msg)
end
}
function init_service()
...
skynet.dispatch("lua", function(_, _, cmd, ...)
LUA_CMD[cmd](...)
end)
end
skynet.start(init_service)
-- target service
function init_service()
...
skynet.dispatch("multicast", function(...)
...
end)
end
skynet.start(init_service)
上述方案中multicastd服务核心只做一个事情:当收到组播通知时,将消息推送到订阅的所有服务中去。这个组播通知可以来自包括服务所在节点内的任何集群内节点,我们常常是把channel id跟某个业务玩法绑定,所有节点约定这个id,target service订阅这个channel后,关联的这个玩法(可能跑在当前或其他节点)有组播需求时,会通知到关心该消息的所有target service。
可以看出,方案并没有区分local channel和remote channel。这里发起组播请求的总是单点玩法节点,而multicastd服务只是作为目标节点,等待组播通知,这里通知消息使用的消息类型也并不是multicastd。我们的业务,广播的需求场景基本是从单点节点单向发出,所有目标节点作为接收方进行接收处理。
标签:...,组播,end,框架,service,skynet,节点,channel From: https://www.cnblogs.com/linxx-/p/18091089