skynet 架構snax源碼分析1---變數注入

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   使用   sp   for   

skynet為了簡化服務的編寫,推出了snax架構,源碼裡也有一個例子pingserver。這是snax原創文章的第一篇,所以先就分析snax架構裡的interface.lua源碼,它的實現應用了一個閉包中的upvalue注入技巧。

凡是架構都得遵循架構的約定,snax有兩個大的約定,一是約定了一組預置的介面init/exit/hotfix;二是accept/response這兩組用來編寫服務的介面。本文,並不涉及這些,而是談accept/response是如何注入給snax服務的。

snax架構裡new一個服務的流程如下,最終調用到snax_inteface裡的interface.lua,該檔案裡只有一個函數:

                        snax.newservice->snax.rawnewservice->snax.interface->snax_interface

    local temp_global = {}    local env = setmetatable({} , { __index = temp_global })    local func = {}    local system = { "init", "exit", "hotfix" }    do        for k, v in ipairs(system) do            system[v] = k            func[k] = { k , "system", v }        end    end

首先看上面這斷代碼,func是函數最終要返回的對象,它 是一個表。在do語句塊裡,func最終會被擴充為添加了三個system介面的數組。接下來就是兩行代碼,

    env.accept = func_id(func, "accept")    env.response = func_id(func, "response")

func_id再做什麼呢,func_id返回的是一個空表,這個表上設定了一個元表,並重寫了元表的__newindex,也就是對該表新鍵賦值時會觸發的操作,env.accept/env.response都是一個帶元表的空表,這裡也就是使用者編寫snax服務需要用到的兩個表,看一下pingserver.lua

function accept.hello()    lock(function()    i = i + 1    print (i, hello)    end)endfunction response.ping(hello)    skynet.sleep(100)    return helloend

只有在snax架構裡,上述代碼才會工作,否則skynet架構會報錯,因為找不不response與accetp對象。那變數是怎麼注入的呢

   do        local path = skynet.getenv "snax"        local errlist = {}        for pat in string.gmatch(path,"[^;]+") do            local filename = string.gsub(pat, "?", name)            local f , err = loader(filename, "bt", G)            if f then                pattern = pat                mainfunc = f                break            else                table.insert(errlist, err)            end        end        if mainfunc == nil then            error(table.concat(errlist, "\n"))        end    end    mainfunc()

上面這段代碼,首先從配置snax路徑裡去尋找到指定的編寫的snax服務,找到之後,就用loader去負載檔案,這個loader預設情況下是是lua API loadfile

loader = loader or loadfile

變數注入依靠的就是這個loadfile,其實呢,我也是從這份代碼裡首次看到loadfile這樣使用,謝謝雲風。一般就只用到第一個參數,第二個參數都沒看到用。

看一下loadfile的C實現

static int luaB_loadfile (lua_State *L) {  const char *fname = luaL_optstring(L, 1, NULL);  const char *mode = luaL_optstring(L, 2, NULL);  int env = (!lua_isnone(L, 3) ? 3 : 0);  /* ‘env‘ index or 0 if no ‘env‘ */  int status = luaL_loadfilex(L, fname, mode);  return load_aux(L, status, env);}static int load_aux (lua_State *L, int status, int envidx) {  if (status == LUA_OK) {    if (envidx != 0) {  /* ‘env‘ parameter? */      lua_pushvalue(L, envidx);  /* environment for loaded function */      if (!lua_setupvalue(L, -2, 1))  /* set it as 1st upvalue */        lua_pop(L, 1);  /* remove ‘env‘ if not used by previous call */    }    return 1;  }  else {  /* error (message is on top of the stack) */    lua_pushnil(L);    lua_insert(L, -2);  /* put before error message */    return 2;  /* return nil plus error message */  }}

首先,luaB_loadfile會看一下env是否設定,然後調用load_aux,這裡如果loadfile的第三個參數正確設定就會調用lua_setupvalue,把env設定為upvalue。

當成功loadfile之後的mainfunc,會立即執行,這時pingserver就能正確找到變數upvalue中的response與accept

最後,skynet源碼裡沒有啟動pingserver的設定檔,下面給一個:

config_snax

root = "./"thread = 8logger = nillogpath = "."harbor = 1address = "127.0.0.1:2526"master = "127.0.0.1:2013"start = "simplesnax"    -- main scriptbootstrap = "snlua bootstrap"    -- The service for bootstrapstandalone = "0.0.0.0:2013"luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"lualoader = "lualib/loader.lua"-- preload = "./examples/preload.lua"    -- run preload.lua before every lua service runsnax = root.."examples/?.lua;"..root.."test/?.lua"cpath = root.."cservice/?.so"-- daemon = "./skynet.pid"

start的simplesnax:

local skynet = require "skynet"local snax = require "snax"skynet.start(function()    local ps = snax.newservice("pingserver", "hello world")end)

最後測試檔案:config_ps

thread = 8mqueue = 256cpath = "./cservice/?.so"logger = nilharbor = 2address = "127.0.0.1:2527"master = "127.0.0.1:2013"start = "testping"luaservice ="./service/?.lua;./test/?.lua;./examples/?.lua"snax = "./examples/?.lua;./test/?.lua"

測試結果:

最後,如果你不想去下源碼,只想馬上嘗試一下,點擊下面的地址,即可在CloudfusionIDE裡線上閱讀源碼,甚至運行(Google/Firefox瀏覽器):http://cloudfusion.cc/ide/cloudfusion/skynet

轉載請註明出處

skynet 架構snax源碼分析1---變數注入

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.