skynet框架 源碼分析 五

 本章講解,skynet的隊列服務。
       隊列服務在源碼中涉及skynet腳本庫,mqueue腳本庫,pingqueue測試服務,pingserver測試服務。

       說說各自的作用。

       mqueue庫:

              1、封裝一個queue消息發送的api==>mqueue.call。

              2、註冊一個queue消息處理函數(message_dispatch)。message_disspatch是在skynet腳本庫的dispatch_message執行完畢後再執行的。如下:

[plain] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. local function dispatch_message(...)  
  2.     local succ, err = pcall(raw_dispatch_message,...)  
  3.     while true do  
  4.         local key,co = next(fork_queue)  
  5.         if co == nil then  
  6.             break  
  7.         end  
  8.         fork_queue[key] = nil  
  9.         local fork_succ, fork_err = pcall(suspend,co,coroutine.resume(co))  
  10.         if not fork_succ then  
  11.             if succ then  
  12.                 succ = false  
  13.                 err = fork_err  
  14.             else  
  15.                 err = err .. "\n" .. fork_err  
  16.             end  
  17.         end  
  18.     end  
  19.     assert(succ, err)  
  20. end  
              在通過取出fork_queue中的元素執行message_dispatch邏輯。這裏面有一個有趣的邏輯。即,當從fork_queue中取出該協程後,forkqueue中該協程被彈出。也就是說,下次不會在fork_queue中再找到該message_dispatch協程。在執行完raw_dispatch_message後,不會在fork_queue中啓動message_dispatch邏輯。那會在哪裏啓動該邏輯呢?看看message_dispatch邏輯。
[plain] view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. local function message_dispatch(f)  
  2.     while true do  
  3.         if #message_queue==0 then  
  4.             thread_id = coroutine.running()  
  5.             skynet.wait()  
  6.         else  
  7.             local msg = table.remove(message_queue,1)  
  8.             local session = msg.session  
  9.             if session == 0 then  
  10.                 if do_func(f, msg) ~= nil then  
  11.                     skynet.fork(message_dispatch,f)  
  12.                     error(string.format("[:%x] send a message to [:%x] return something", msg.addr, skynet.self()))  
  13.                 end  
  14.             else  
  15.                 local data, size = skynet.pack(do_func(f,msg))  
  16.                 -- 1 means response  
  17.                 c.send(msg.addr, 1, session, data, size)  
  18.             end  
  19.         end  
  20.     end  
  21. 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庫。就這些.......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章