skynet指定的多个服务绑定同一个线程

为什么会需要多个服务绑定一个线程?skynet节点的线程数量是可以配置的,但是你不可能配置非常多吧?如果我们一个节点有非常多的服务,我们想其中某些服务不能卡,那么就需要把服务绑定线程不和其他服务共享线程。

我们有一些服务,业务很简单,虽然不怎么吃资源,但是要求不能卡,都需要绑定线程,如果给每一个服务都绑定线程,剩下的留给其他服务共享,可能会资源浪费。绑定的服务消耗了太多的线程,饱的饱死,饿得饿死。

所以我们需要把那些需要独立线程,本身其实不怎么吃资源的,给他们绑定同一个线程。

-- thread_proxy.lua(线程代理服务)

Lua 复制代码
-- thread_proxy.lua(线程代理服务)
local skynet = require "skynet"
local logger = require "base.logger"
local thread_id = nil  -- 要绑定的线程ID(比如 3)
local target_services = {}  -- 要共享该线程的3个服务
-- 注册需要共享线程的服务
function CMD.register_service(svc_name, svc_handle)
    target_services[svc_name] = svc_handle
    logger.info(string.format("服务%s注册到线程%d的代理", svc_name, thread_id))
end
-- 转发消息到目标服务
function CMD.forward_msg(svc_name, cmd, ...)
    local svc = target_services[svc_name]
    if not svc then
        logger.error("服务未注册:", svc_name)
        return
    end
    -- 在当前线程内调用目标服务的逻辑(核心:保证在同一个线程执行)
    skynet.call(svc, "lua", cmd, ...)
end
skynet.start(function()
    -- 1. 绑定到指定线程(thread_id需和配置的thread数匹配,比如3)
    thread_id = tonumber(skynet.getenv("bind_thread_id")) or 3
    skynet.set_thread(thread_id)  -- 关键:绑定到指定ID的线程
    logger.info("线程代理服务绑定到线程:", thread_id)
    -- 2. 注册消息处理函数
    skynet.dispatch("lua", function(session, source, cmd, ...)
        local f = CMD[cmd]
        if f then
            skynet.ret(skynet.pack(f(...)))
        else
            skynet.ret(skynet.pack(nil, "未知命令:"..cmd))
        end
    end)
end)

-- target_service1.lua

Lua 复制代码
-- target_service1.lua(目标服务1,2/3同理)
local skynet = require "skynet"
local logger = require "base.logger"
local proxy_svc = nil  -- 线程代理服务的句柄
-- 实际业务逻辑(会在代理线程中执行)
function CMD.do_business(...)
    logger.info("服务1在线程中处理业务:", ...)
    -- 你的业务逻辑(比如场景管理、玩家数据处理)
    return "success"
end
skynet.start(function()
    -- 1. 获取线程代理服务句柄
    proxy_svc = skynet.uniqueservice("thread_proxy")
    -- 2. 注册到代理服务
    skynet.call(proxy_svc, "lua", "register_service", "service1", skynet.self())
    -- 3. 所有消息转发给代理
    skynet.dispatch("lua", function(session, source, cmd, ...)
        -- 转发到代理服务,由代理在指定线程中执行
        local ret = skynet.call(proxy_svc, "lua", "forward_msg", "service1", cmd, ...)
        skynet.ret(skynet.pack(ret))
    end)
end)

-- 节点入口

Lua 复制代码
-- 节点入口
local skynet = require "skynet"
skynet.start(function()
    -- 1. 先启动线程代理服务(必须最先启动)
    local proxy = skynet.uniqueservice("thread_proxy")

    -- 2. 启动3个目标服务
    local s1 = skynet.newservice("target_service1")
    local s2 = skynet.newservice("target_service2")
    local s3 = skynet.newservice("target_service3")

    -- 3. 测试:调用3个服务的业务逻辑,验证都在线程3执行
    skynet.call(s1, "lua", "do_business", "服务1测试")
    skynet.call(s2, "lua", "do_business", "服务2测试")
    skynet.call(s3, "lua", "do_business", "服务3测试")
end)
相关推荐
lifewange6 小时前
Postman如何实现接口自动化
自动化·lua·postman
上海合宙LuatOS1 天前
LuatOS扩展库API——【 excloud】AirCloud云平台控制
物联网·lua·luatos·合宙aircloud平台
he___H1 天前
Nginx+lua+openresty
nginx·lua·openresty
最好有梦想~2 天前
嵌入式Linux Lua使用ZeroBrane远程调试
linux·嵌入式硬件·lua
chushiyunen3 天前
lua脚本笔记、redis使用lua解锁
redis·笔记·lua
深蓝轨迹3 天前
Redis+Lua实现秒杀优化
数据库·redis·lua
qhs15734 天前
解决 LuaJIT 报错:unknown luaJIT command or jit.* modules not installed
lua
luanma1509804 天前
Laravel 8.X重磅特性全解析
前端·javascript·vue.js·php·lua
luanma1509804 天前
Laravel 7.X核心特性深度解析
android·开发语言·php·lua·laravel
上海合宙LuatOS5 天前
LuatOS扩展库API——【air153C_wtd】外部硬件看门狗
物联网·lua·air153c_wtd 库