skynet 入門筆記(2):service 消息收發

Skynet 入門筆記(2):Service 消息收發

編寫第一個 service 成功了,接下來考慮多個 service 之間如何通訊的問題。css

skynet 是單進程多線程框架,每一個 lua service 獨立運行在本身的 lua vm 裏,採用 actor 併發模型。git

這篇博客要實現的是讓一個 service 發送消息,另外一個 service 處理消息。github

actor 併發模型

Actor模型又稱爲參與者模型,基本理念是每一個併發的線程(或者進程、服務等其餘併發的東西)都是一個參與者,參與者之間互相發送消息,決定如何迴應消息或者啓動更多參與者。bootstrap

用人話來講,就是參與者給另外一個參與者發送消息,而後繼續幹本身的事情;收到消息的參與者決定要怎麼處理消息:作點什麼,建立新參與者,或者拋棄這個消息。api

skynet 啓動新 service

依照前文配置 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.newservicesession

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的介紹以下。

  1. register(name) 給當前服務起一個字符串名。
  2. dispatch(type, func) 爲 type 類型的消息設定一個處理函數。

回調函數的簽名是這樣:

function (session, source, ...)

其中dispatch的回調函數前兩個參數分別是這樣解釋。

  1. session是爲了確保能將消息處理結果對應到某條消息,就像是服務器收到同一個客戶端的2條網絡請求,一條請求js一條請求css,若是誰先處理完誰就返回的話,可能css的請求就收到了js的內容。
  2. 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!
相關文章
相關標籤/搜索