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)
相关推荐
BuHuaX1 天前
Lua 与 ToLua:运行机制及热更新原理
开发语言·unity·junit·c#·lua
努力努力再努力wz1 天前
【Lua 入门系列】模块与包(一):从多文件组织到require 运行时加载机制、模块缓存、预加载搜索与 Lua 文件搜索机制
开发语言·junit·lua
UWA1 天前
多人战斗中Lua持续高耗时,是瞬时峰值还是高频调用在作祟
性能优化·lua·游戏开发
努力努力再努力wz2 天前
【Lua 入门系列】从执行模型到事件驱动:一文理解 Lua 有栈协程、挂起恢复与协作式调度
开发语言·lua
努力努力再努力wz2 天前
【Lua 入门系列】Lua数据结构:从 Table 出发,一文串联数组、链表、栈、队列、集合、映射与树的实现原理
数据结构·链表·lua
努力努力再努力wz3 天前
【Lua入门系列】从 Table 到元表与元方法:一文理解 Lua 的行为扩展机制
开发语言·junit·lua
麻瓜code4 天前
秒杀优化三连:Lua + 阻塞队列 + Redis Stream,响应从 3.4 秒到毫秒级
redis·junit·lua
努力努力再努力wz4 天前
【Lua 入门系列】Lua 函数深入理解:函数对象、多返回值、可变参数、闭包、递归与尾调用优化
开发语言·lua
hey you~4 天前
云呼叫中心坐席自动分配实战:ACD 策略、Redis+Lua 实现与排查清单
数据库·redis·lua·云呼叫中心·acd·坐席分配·坐席状态机
我不会起名字3224 天前
Redis pipeline 用了反而更慢:3 类误用与正确的批量姿势
redis·pipeline·lua·rtt·批量