本章讲解,skynet的队列服务。
队列服务在源码中涉及skynet脚本库,mqueue脚本库,pingqueue测试服务,pingserver测试服务。
说说各自的作用。
mqueue库:
1、封装一个queue消息发送的api==>mqueue.call。
2、注册一个queue消息处理函数(message_dispatch)。message_disspatch是在skynet脚本库的dispatch_message执行完毕后再执行的。如下:
local function dispatch_message(...)
local succ, err = pcall(raw_dispatch_message,...)
while true do
local key,co = next(fork_queue)
if co == nil then
break
end
fork_queue[key] = nil
local fork_succ, fork_err = pcall(suspend,co,coroutine.resume(co))
if not fork_succ then
if succ then
succ = false
err = fork_err
else
err = err .. "\n" .. fork_err
end
end
end
assert(succ, err)
end
在通过取出fork_queue中的元素执行message_dispatch逻辑。这里面有一个有趣的逻辑。即,当从fork_queue中取出该协程后,forkqueue中该协程被弹出。也就是说,下次不会在fork_queue中再找到该message_dispatch协程。在执行完raw_dispatch_message后,不会在fork_queue中启动message_dispatch逻辑。那会在哪里启动该逻辑呢?看看message_dispatch逻辑。
local function message_dispatch(f)
while true do
if #message_queue==0 then
thread_id = coroutine.running()
skynet.wait()
else
local msg = table.remove(message_queue,1)
local session = msg.session
if session == 0 then
if do_func(f, msg) ~= nil then
skynet.fork(message_dispatch,f)
error(string.format("[:%x] send a message to [:%x] return something", msg.addr, skynet.self()))
end
else
local data, size = skynet.pack(do_func(f,msg))
-- 1 means response
c.send(msg.addr, 1, session, data, size)
end
end
end
end
有一个关键接口:skynet.wait,让当前协程以sleep的状态保留在当前服务中,并切出协程回到lua主线程。每次skynet库在执行suspend后会调用dispatch_wakeup接口。若,该协程在wakeup_session中被标志了true,那么在dispatch_wakeup中,会重新启动message_dispatch协程。
由于message_dispatch中有一个循环体,所以,在没有return,break关键字的正常情况下,该服务中的message_dispatch接口会一直执行下去。message_dispatch每次会从message_queue表中取一个元素,执行一次逻辑。
3、注册一个queue消息队列添加函数(dispatch)。将新到的queue消息添加到message_queue表中。
pingqueue服务:
1、作为一个消息队列服务,按顺序调用队列中的服务。意思就是,向该服务发送的所有queue消息,都以先进先出的方式处理。该服务中调用了mqueue.register,注册了一个message_dispatch回调在fork_queue。该服务负责排序。
pingserver服务:
1、响应消息的服务。被太多用途。
说了这么多,谈谈实战。
什么情况下会用到这种类型的服务呢?
目前还没想好,想好了添上去..................先吃饭........
2014-3-26 补充:
本来想再写一篇续,来继续本文所说的mqueue用法。不过,整个设计完善的差不多的时候发现,mqueue库只是其中的基础组件。所以就在这里补充说几句。
我打算在我的登入排队系统中使用mqueue库。就这些.......