skynet(v1.4.0)学习笔记
-
登录流程
-
游戏中一般为了减轻登录服的压力,采用主从登录服务设计
local function login(conf)local name = "." .. (conf.name or "login")skynet.start(function()local loginmaster = skynet.localname(name)if loginmaster thenlocal auth_handler = assert(conf.auth_handler)launch_master = nilconf = nillaunch_slave(auth_handler)elselaunch_slave = nilconf.auth_handler = nilassert(conf.login_handler)assert(conf.command_handler)skynet.register(name)launch_master(conf)endend) 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 = nilend) 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.queueskynet.start(function()local q = queue()skynet.dispatch("lua", function(seesion, _ , command, ...)q(skynet.call,A,"lua","xxx",...) --A服务可以sleep x秒再给retend) end
-
-
-
协程
- 如果主协程create一个协程,那么参数就是resume的参数,如果是挂起一个协程,那么resume协程的返回值是yield的参数