skynet newservice API參考

local skynet = require("skynet")vim

skynet.start(start_func)session

c服務snlua啓動後執行的第一個lua文件裏面的主邏輯一定是skynet.start(start_func),由此開始運行lua服務的邏輯數據結構

start_func是當前lua服務的初始化函數,也是當前服務的第一個協程的函數框架

以後在收到非response消息時dispatch_message會建立更多的協程來作邏輯異步

而調用skynet.start(start_func)的主線程會調度上述這些協程(yield)函數

dispatch_message(...) ui

這就是ctx的消息處理函數(skynet_context.skynet_cb, 返回零(假)時釋放消息的內存.那麼lua層如何控制呢?c.callback(dispatch_message,false)就是釋放內存,c.callback(dispatch_message,true)不釋放內存,具體參見vim -t _callback.那麼lua層如何控制發消息時不作複製呢?我看skynet.send/call/rawcall都不支持對複製的控制,參見vim -t _send. 底層的默認處理是:對於Lua string直接複製,對於lightuserdata不復制,對於其餘類型報錯)lua

dispatch_message將是本服務的發動機(消息驅動機),也就是底層工做線程拿到本服ctx.mq中的一個消息後執行的消息處理函數(vim -t _dispatch_message, 底層由worker thread取到消息後調用這個函數而觸發lua函數的調用),也就是本lua服的主線程(雖然線程ID不固定)spa

dispatch_message每處理完mq中的一個消息都要遍歷並執行消息處理過程當中fork而沒運行的新協程(遍歷fork_queue並coroutine.resume())prototype

對於收到的每一個非response(prototype!=skynet.PTYPE_RESPONSE)消息啓動一個新協程X,用該協程來運行協議類型對應的dispatch函數來處理消息

對於收到的每一個response消息,根據session從session_id_coroutine取出協程並恢復執行

協程X運行業務邏輯時可能會「對其餘服務作請求並等待結果」或者「睡眠幾秒」,這時協程X用yield拋出「CALL」/「SLEEP」等返回值並掛起,主線程根據yield拋出的值對協程作不一樣處理

CALL -> 協程X已對其餘服務發出請求並等待迴應 -> 主線程把協程X記錄到session_id_coroutine中,下次收到對應的response消息(sessionID一致)時喚醒

SLEEP -> 協程X[已調用skynet.sleep(ti)等定時器返回]或[已調skynet.wait()等其餘服務返回,這種狀況通常須要用skynet.wakeup()來喚醒,不然協程可能永遠沉睡下去了] -> 主線程把協程X記錄到session_id_coroutine,並記錄sleep_session,對於sleep_session須要用skynet.wakeup(co)喚醒 (session_id_coroutine和sleep_session二者怎麼維持數據一致,這個細節還須要結合實例再看看 markbyxds )

skynet.newservice(name,...)

建立lua服務 skynet.rawcall(".launcher", "lua" , skynet.pack("LAUNCH", "snlua", name, ...))

實際上是skynet_context_new(module_name("snlua"), param("cmaster"))

即,用snlua服跑着一個lua邏輯服(service/cmaster.lua),snlua創造了一個lua環境的沙盒

除了service/launch.lua自身之外,其餘lua服務通常都是由service/launch.lua這個lua服負責建立的

固然,launch服最終仍是調用的skynet.launch("snlua","xxx")來建立服務

skynet.launch 

建立c服務, lualib-src/lua-skynet.c -> skynet_command(CTX,"LAUNCH",..) -> skynet_context_new(mod,args)

對於skynet.launch("snlua","xxx"),這是建立c服務snlua而後在它上面跑lua服務xxx

skynet.monitor(service, query)    監控服務退出,細節還沒仔細看 markbyxds

skynet.uniqueservice(global,...) 

建立一個惟一的服務,調用屢次service/***.lua也只啓一個實例,好比clusterd和multicastd

global=true時,在全部節點之間是惟一的

實際上是用skynet.call(異步變同步)的方式讓service_mgr服務建立目標服務(相似於通知launch服建立服務同樣)

service_mgr這邊如已建立則直接返回服務地址;如沒則建立;如正在建立則等結果

skynet.queryservice(global,...) global=true時

若是尚未建立過目標服務則一直等下去,直到目標服務被(其餘服務觸發而)建立

skynet.rawcall 

向目標服發送無協議的消息並返回response,協程掛起等返回,用同步代碼的樣式實現異步邏輯

當 A call B 時,若是 B 在迴應前就退出了,A 會收到一條異常,並正確的傳播到 A 裏的 call 調用處;

當 A call B ,而 B 在迴應前,A 本身退出了,B 也會收到一條異常,提示 A 已經不在了。但不會影響 B 的執行流程,只是讓框架回收一些必要的相關資源。

skynet.call 跟skynet.rawcall的區別是向目標服發送指定協議的消息

skynet.send 跟skynet.call的區別是僅僅發消息而已,不關心返回值也不會讓當前協程掛起(非request-response模式)

skynet.wait() 

把當前協程掛起放入session_id_coroutine/sleep_session

當收到等待的消息(會把消息對應的正在等待session放入wakeup_session中)後該協程恢復執行

skynet.sleep(ti) 

相似於skynet.wait(),只是要事先通知底層定時器

等定時器(在ti時間達到後)發來消息時該協程恢復執行

skynet.wakeup(co) 

若是協程co正處於掛起等待的狀態(在sleep_session中)則把它加入wakeup_session

本服務的主協程會在調度過程當中把wakeup_session中的協程喚醒執行

skynet.ret 在當前協程(爲處理請求方消息而產生的協程)中給請求方(消息來源)的消息作迴應

skynet.retpack 跟skynet.ret的區別是向請求方做迴應時要用skynet.pack打包

skynet.register_protocol 

註冊協議:

協議名(name)

協議ID(id)

發送消息的打包函數(pack)

接收消息的拆包函數(unpack)

接收消息的(分發)處理函數(dispatch)

已註冊的協議記錄在lualib/skynet.lua:proto這個數據結構上

每一個服務會默認初始化lua/response/error這幾種協議

skynet.dispatch(typename, func) 

修改以typename爲協議名的協議:用func這個函數來做爲協議的dispatch函數(默認的lua協議沒提供dispatch,須要使用者根據業務須要寫)

skynet.fork 

建立一個新的協程

這裏有作協程對象池來加速,相似於咱們項目中的線程池,建立一堆協程並掛起,接到業務後拿協程跑業務邏輯

skynet.register(name) 

註冊當前服務的名字(默認用:%x做爲name,本地服務的自定義名以.打頭)

把<handleId + name>記錄到handle_storage->name,參數必須符合本地服務的命名規範

skynet.self() 返回當前服務的handleID,若是還沒註冊就先註冊(相似於skynet.register)

skynet.harbor(addr) return 「addr(ctx的handleID)對應的harborID",boolean(是否遠端節點)

skynet.address(addr) return "addr(ctx的handleID或者name)對應的name(string,:%x或者自定義名)" 

相關文章
相關標籤/搜索