skynet(v1.4.0)学习笔记

skynet(v1.4.0)学习笔记

  • 登录流程

    • 游戏中一般为了减轻登录服的压力,采用主从登录服务设计

      local function login(conf)
      	local name = "." .. (conf.name or "login")
      	skynet.start(function()
      		local loginmaster = skynet.localname(name)
      		if loginmaster then
      			local auth_handler = assert(conf.auth_handler)
      			launch_master = nil
      			conf = nil
      			launch_slave(auth_handler)
      		else
      			launch_slave = nil
      			conf.auth_handler = nil
      			assert(conf.login_handler)
      			assert(conf.command_handler)
      			skynet.register(name)
      			launch_master(conf)
      		end
      	end)
      end
      
    • 先看主服务,conf里的auth_handler肯定不要,交给从服务去验证,launch_slave函数也不要,给主服务注册一个别名可以用来区分这是主服务还是从服务

    • 主服务就好像是一个套接字入口,验证就交给从服务

    • 如果是比较大型的游戏,应该就一个登录节点,验证完之后,根据serverId转发到对应游戏服,这种设计登录服的压力比较大。

    • 直接游戏节点启一个登录服,客户端直接连登录服,然后转发到对应游戏服的网关就好了

    • 从服务,账号密码验证之后,这里要直接解析login.pb就好了,登录服只要注册一条协议就好了

    • load_config给配置环境加一个include函数 + 隔离全局,如果load使用全局环境的话,不能使用局部函数,如果不是局部函数会污染全局环境的环境,这样写配置文件里可以直接写 include "xxx"

  • skynet.start函数

    • function skynet.start(start_func)
      	c.callback(skynet.dispatch_message)
      	init_thread = skynet.timeout(0, function(_1, _2,_3,_4)
      		print("init_service", _1, _2, _3, _4)
      		skynet.init_service(start_func)
      		init_thread = nil
      	end)
      end
      
    • 这个函数是服务启动的入口,start_func是服务启动函数,c.callback(skynet.dispatch_message),注册lua消息回调函数,接下来执行skynet.timeout函数,0表示c 层会发一个 PTYPE_RESPONSE(1) 的消息回来,这时 session_id_coroutine[session] 对应的协程被唤醒,内部是创建一个协程去接受timeout的消息,session_id_coroutine[session] = co, session则表示唯一id,c层收到timeout发送的消息,lua层skynet.dispatch_message开始处理消息,skynet.dispatch_message是用lua虚拟机的主协程处理的,但是消息处理还是用的工作协程处理的,流程是唤醒timeout创建的协程,工作协程设置为当前唤醒的协程,执行start_func,start_func一般newservice会call其它服务,也会设计到协程挂起,skynet.call先发送一条lua消息到指定服务(launcher),然后设置session对应工作协程,挂起这个协程后,suspend的参数就是suspend(co, result, "SUSPEND"),执行完主协程的逻辑,等另外一个服务执行完初始化之后调response()给调用newservice服务发消息。

    • c驱动的回调就是主协程执行的

    • skynet.call

      • 获得一个session,注册一个session对应的工作协程,而不是调用co_create,然后挂起这个协程
    • launcher服务

      • 创建和管理lua服务的服务,command.LAUNCH(_, service, ...),在这个服务中接受的如果是lua消息类型,p.dispatch:lua层的消息类型回调函数,去协程池拿一个协程,设置session_coroutine_id[co] = session,session_coroutine_address[co] = source,然后协程执行launch_service(service, ...),根据skynet.context()拿到session,instance[inst] = response设置服务初始化好之后的回调函数,LAUNCHOK之后执行response()
    • skynet.queue

      • 比如agent服务,接收一条协议然后call挂起了agent服务,协议没处理完,current_thread = 当前运行的协程,引用+1,然后执行f挂起了,然后又来一条协议,由于当前协程不等于运行中的协程,就会塞进thread_queue里面,然后挂起这个协程,这个时候第一条协程开始回消息了,执行完之后,就开始wakeup后面一条协程,wakeup也就是插进wakeup_queue,也就是执行调度完这条协程,就立马执行了,相当于队列,伪代码如下

        local queue = skynet.queue
        
        skynet.start(function()
            local q = queue()
        	skynet.dispatch("lua", function(seesion, _ , command, ...)
                        q(skynet.call,A,"lua","xxx",...) --A服务可以sleep x秒再给ret
        	end)
        end
        
  • 协程

    • 如果主协程create一个协程,那么参数就是resume的参数,如果是挂起一个协程,那么resume协程的返回值是yield的参数
posted @ 2025-11-17 16:50  liter_wave  阅读(1)  评论(0)    收藏  举报