編寫第一個 service 成功了,接下來考慮多個 service 之間如何通訊的問題。css
skynet 是單進程多線程框架,每一個 lua service 獨立運行在本身的 lua vm 裏,採用 actor 併發模型。git
這篇博客要實現的是讓一個 service 發送消息,另外一個 service 處理消息。github
Actor模型又稱爲參與者模型,基本理念是每一個併發的線程(或者進程、服務等其餘併發的東西)都是一個參與者,參與者之間互相發送消息,決定如何迴應消息或者啓動更多參與者。bootstrap
用人話來講,就是參與者給另外一個參與者發送消息,而後繼續幹本身的事情;收到消息的參與者決定要怎麼處理消息:作點什麼,建立新參與者,或者拋棄這個消息。api
依照前文配置 skynet服務器
修改project/service/main.lua
。網絡
-- main.lua local skynet = require "skynet" skynet.start(function() -- print("Hello world") skynet.newservice "myservice/worker" skynet.newservice "myservice/msg_dispatcher" skynet.exit() end)
主要修改的地方是加入了兩行skynet.newservice
session
api參考文檔在這裏多線程
確實挺簡陋的,就一句話。併發
newservice(name, ...) 啓動一個名爲 name 的新服務。
name
參數注意用相對於project/service
的路徑便可,不用加lua
的後綴名。
在project/service
裏建立目錄myservice
,而後在裏面建立新文件msg_dispatcher.lua
-- msg_dispatcher.lua local skynet = require "skynet" function sendmsg() skynet.send("worker", "lua", "say", "Hello world!") skynet.timeout(100, sendmsg) end skynet.start(function() skynet.timeout(100, sendmsg) end)
其中 function skynet.timeout(ti, func)
是定時器,第一個參數是時間,單位是 1/100 秒,第二個參數是回調函數。
而後是function skynet.send(addr, type, ...)
,第一個addr
是服務的地址,這個地址能夠是服務的32位整數識別id,也能夠是字符串別名;別名須要該服務自行註冊才能使用。第二個type
參數是消息類型,經常使用的就是lua
雖然我也不知道爲啥經常使用但你們都這麼用。後面的變長參數通常來講第一個約定是命令類型,再日後是命令參數,看下面的處理就知道了。
在project/service/myservice
裏建立文件worker.lua
,而後這麼寫。
-- work.lua local CMD = {} CMD.say = function (text) print(text) end skynet.start(function() skynet.register("worker") skynet.dispatch("lua", function(session, source, cmd, ...) print("[worker] received `"..cmd.."`") local f = CMD[cmd] end) end)
幾個api的介紹以下。
register(name)
給當前服務起一個字符串名。dispatch(type, func)
爲 type 類型的消息設定一個處理函數。回調函數的簽名是這樣:
function (session, source, ...)
其中dispatch
的回調函數前兩個參數分別是這樣解釋。
session
是爲了確保能將消息處理結果對應到某條消息,就像是服務器收到同一個客戶端的2條網絡請求,一條請求js一條請求css,若是誰先處理完誰就返回的話,可能css的請求就收到了js的內容。source
是消息的來源,是一個整數id。後面的 cmd 參數其實也屬於變長參數的一部分,可是通常約定變長參數第一個參數是服務要執行的命令 (RPC的感受),因此就給了個 cmd 的名字。變長參數剩餘的部分就是處理函數的參數了。
固然用其餘處理方法也沒問題,只是經常使用模式。
[:00000001] LAUNCH logger [:00000002] LAUNCH snlua bootstrap [:00000003] LAUNCH snlua launcher [:00000004] LAUNCH snlua cdummy [:00000005] LAUNCH harbor 0 4 [:00000006] LAUNCH snlua datacenterd [:00000007] LAUNCH snlua service_mgr [:00000008] LAUNCH snlua main [:00000009] LAUNCH snlua myservice/msg_dispatcher [:0000000a] LAUNCH snlua myservice/worker [:00000008] KILL self [:00000002] KILL self [room_mgr] received `say` from `10` Hello world! [room_mgr] received `say` from `10` Hello world! [room_mgr] received `say` from `10` Hello world!