1. 程式人生 > >skynet源碼分析:服務

skynet源碼分析:服務

輕量 查詢 開發 插入 適用於 text 函數 基本 agent

skynet是為多人在線遊戲打造的輕量級服務端框架,使用c+lua實現。使用這套框架的一個好處就是,基本只需要lua,很少用到c做開發,一定程度上提高了開發效率。

skynet的例子是怎麽調用的
服務器:
simpledb.lua: skynet.register “SIMPLEDB” 向skynet裏註冊一個服務
agent.lua: skynet.call(“SIMPLEDB”, “text”, text) 調用相應的服務
main.lua: skynet.newservice(“simpledb”) 啟動一個服務
以上函數都在\lualib\skynet.lua 文件內

以下是幾個寫服務時經常要用到的函數。

newservice(name, ...) 啟動一個名為 name 的新服務。
uniqueservice(name, ...) 啟動一個唯一服務,如果服務該服務已經啟動,則返回已啟動的服務地址。
queryservice(name) 查詢一個由 uniqueservice 啟動的唯一服務的地址,若該服務尚未啟動則等待。
localname(name) 返回同一進程內,用 register 註冊的具名服務的地址。

newservice可以在一個進程裏啟動多個服務,這適用於無狀態的服務。
uniqueservice則是類似於設計模式中的單件(singleton),這適用於需要唯一性的服務。舉個例子,比如寫日誌,只想寫一份。或者是全局共享的數據。 消息機制 SKYNET設計綜述講到模塊被稱為服務。“服務間可以自由發送消息。每個模塊可以向 Skynet 框架註冊一個 callback 函數,用來接收發給它的消息。”還提到“把一個符合規範的 C 模塊,從動態庫(so 文件)中啟動起來,綁定一個永不重復(即使模塊退出)的數字 id 做為其 handle 。Skynet 提供了名字服務,還可以給特定的服務起一個易讀的名字,而不是用 id 來指代它。id 和運行時態相關,無法保證每次啟動服務,都有一致的 id ,但名字可以。”今天要分析的兩個文件skynet_handle.c和skynet_handle.h就是實現名字服務的。
skynet_handle.c實際上就做了兩個核心的事情,一是給服務分配一個handle,二是把handle和name關聯起來。

把handle和name關聯起來比較容易懂,實際上使用一個數組,關聯的時候使用二分查找到數組裏查名字,如果名字不存在,就插入一個元素,然後把名字和handle關聯起來。插入元素的時候,如果數組空間不足了,就擴容為原來的2倍。

而給服務分配handle稍復雜一些,實際上也是使用一個slot數組,數組下標使用的是一個hash,數組元素指向服務的上下文。這個hash的算法是比較簡單粗暴的,就是看從handle_indx開始累計到slot_size,看中間有沒有空閑的下標(也就是下標指向為null的),如果遍歷完了還是沒有,就把slot擴大一倍,還是沒有就再擴大一倍,直到找到空位為止,或者是slot長度超出限制為止。

取到了handle以後呢,還要將harbor id附到handle的高8位。


參考: skynet源碼分析(3)--消息名字和ID之handle

skynet教程(3)--服務的別名

skynet源碼分析:服務