skynet消息調(diào)度及處理

skynet內(nèi)部服務(wù)都是由一個(gè)一個(gè)的消息所驅(qū)動(dòng)驹暑,每個(gè)服務(wù)的上下文結(jié)構(gòu)體struct skynet_context有個(gè)字段struct message_queue *queue描述其消息隊(duì)列术唬,所有服務(wù)的消息隊(duì)列掛在全局消息對(duì)列的列表struct global_queue *Q

skynet在啟動(dòng)時(shí)會(huì)啟動(dòng)config->thread個(gè)worker線程來(lái)處理所有服務(wù)的消息苫幢,worker線程的入口函數(shù)為static void *thread_worker(void *p)友多,其處理邏輯如下:

  1. 如果當(dāng)前要處理的消息隊(duì)列為空啥么,則從全局消息隊(duì)列的列表中取下一個(gè)消息隊(duì)列
  2. 對(duì)消息隊(duì)列中的每個(gè)消息硼砰,調(diào)用該消息隊(duì)列所屬服務(wù)的回調(diào)函數(shù)糠赦,每次至少處理一個(gè)消息碎罚,之多處理消息隊(duì)列長(zhǎng)度右移weight個(gè)消息磅废,其中weight是事先配置好的
static int weight[] = { 
        -1, -1, -1, -1, 0, 0, 0, 0,
        1, 1, 1, 1, 1, 1, 1, 1, 
        2, 2, 2, 2, 2, 2, 2, 2, 
        3, 3, 3, 3, 3, 3, 3, 3, };

比如配置啟動(dòng)n個(gè)worker線程,第i個(gè)線程的weight為:當(dāng)i小于weight數(shù)組長(zhǎng)度時(shí)荆烈,線程weightweight[i-1]拯勉,否則為0

每個(gè)服務(wù)的消息隊(duì)列都會(huì)被worker進(jìn)程公平的進(jìn)行處理,但是每個(gè)線程一次處理的消息個(gè)數(shù)由工作線程配置的權(quán)重決定憔购。

下面以snlua為例理解消息回調(diào)處理宫峦,在dispatch_message函數(shù)中,通過(guò)調(diào)用服務(wù)的回調(diào)函數(shù)來(lái)讓服務(wù)處理其收到的消息:
ctx->cb(ctx, ctx->cb_ud, type, msg->session, msg->source, msg->data, sz)

snlua是執(zhí)行lua服務(wù)的沙盒環(huán)境玫鸟,啟動(dòng)一個(gè)lua服務(wù)之后导绷,在lua代碼中會(huì)設(shè)置回調(diào)函數(shù),通常在skynet.lua文件中的skynet.start中設(shè)置c.callback(skynet.dispatch_message)屎飘,c.callback調(diào)用的是:

  83 static int
  84 _callback(lua_State *L) {
  85     struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
  86     int forward = lua_toboolean(L, 2);
  87     luaL_checktype(L,1,LUA_TFUNCTION);
  88     lua_settop(L,1);
  89     lua_rawsetp(L, LUA_REGISTRYINDEX, _cb);
  90
  91     lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
  92     lua_State *gL = lua_tothread(L,-1);
  93
  94     if (forward) {
  95         skynet_callback(context, gL, forward_cb);
  96     } else {
  97         skynet_callback(context, gL, _cb);
  98     }
  99
 100     return 0;
 101 }
  • 85行獲取服務(wù)的上下文結(jié)構(gòu)妥曲,此upvalue是在啟動(dòng)次服務(wù)的時(shí)候設(shè)置的
  • 89行在注冊(cè)表中設(shè)置_cb=>skynet.dispatch_message
  • 91-92行獲取服務(wù)的LUA狀態(tài)機(jī)結(jié)構(gòu)
  • 95或者97行設(shè)置服務(wù)上下結(jié)構(gòu)體中的回調(diào)函數(shù)為_cb,回調(diào)函數(shù)私有數(shù)據(jù)為L(zhǎng)UA狀態(tài)機(jī)gL

下面來(lái)分析回調(diào)函數(shù)_cb钦购,任何LUA沙盒服務(wù)收到的消息的回調(diào)函數(shù)入口都是_cb

  30 static int
  31 _cb(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
  32     lua_State *L = ud;
  33     int trace = 1;
  34     int r;
  35     int top = lua_gettop(L);
  36     if (top == 0) {
  37         lua_pushcfunction(L, traceback);
  38         lua_rawgetp(L, LUA_REGISTRYINDEX, _cb);
  39     } else {
  40         assert(top == 2);
  41     }
  42     lua_pushvalue(L,2);
  43
  44     lua_pushinteger(L, type);
  45     lua_pushlightuserdata(L, (void *)msg);
  46     lua_pushinteger(L,sz);
  47     lua_pushinteger(L, session);
  48     lua_pushinteger(L, source);
  49
  50     r = lua_pcall(L, 5, 0 , trace);
  51
  52     if (r == LUA_OK) {
  53         return 0;
  54     }
  55     const char * self = skynet_command(context, "REG", NULL);
  56     switch (r) {
  57     case LUA_ERRRUN:
  58         skynet_error(context, "lua call [%x to %s : %d msgsz = %d] error : " KRED "%s" KNRM, source , self, session, sz, lua_tostring(L,-1));
  59         break;
  60     case LUA_ERRMEM:
  61         skynet_error(context, "lua memory error : [%x to %s : %d]", source , self, session);
  62         break;
  63     case LUA_ERRERR:
  64         skynet_error(context, "lua error in error : [%x to %s : %d]", source , self, session);
  65         break;
  66     case LUA_ERRGCMM:
  67         skynet_error(context, "lua gc error : [%x to %s : %d]", source , self, session);
  68         break;
  69     };
  70
  71     lua_pop(L,1);
  72
  73     return 0;
  74 }
  • 32-38行在LUA狀態(tài)機(jī)的棧中設(shè)置即將執(zhí)行的LUA函數(shù)及參數(shù)檐盟,依次是tracebackskynet.dispatch_message押桃,type葵萎,msgsz怨规,session陌宿,source
  • 50行在保護(hù)模式執(zhí)行skynet.dispatch_message函數(shù),在此函數(shù)進(jìn)行真正消息處理

以上粗略的分析了skynet框架是如何調(diào)度每個(gè)服務(wù)的消息隊(duì)列波丰,以及如何通過(guò)回調(diào)函數(shù)來(lái)對(duì)服務(wù)的消息進(jìn)行處理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壳坪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子掰烟,更是在濱河造成了極大的恐慌爽蝴,老刑警劉巖沐批,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝎亚,居然都是意外死亡九孩,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)发框,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)躺彬,“玉大人,你說(shuō)我怎么就攤上這事梅惯∠苡担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵铣减,是天一觀的道長(zhǎng)她君。 經(jīng)常有香客問(wèn)我,道長(zhǎng)葫哗,這世上最難降的妖魔是什么忘古? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任河闰,我火速辦了婚禮泼掠,結(jié)果婚禮上押搪,老公的妹妹穿的比我還像新娘。我一直安慰自己捺典,他們只是感情好灭翔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著辣苏,像睡著了一般肝箱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上稀蟋,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天煌张,我揣著相機(jī)與錄音,去河邊找鬼退客。 笑死骏融,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萌狂。 我是一名探鬼主播档玻,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茫藏!你這毒婦竟也來(lái)了误趴?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤务傲,失蹤者是張志新(化名)和其女友劉穎凉当,沒(méi)想到半個(gè)月后枣申,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡看杭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年忠藤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片楼雹。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡模孩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贮缅,到底是詐尸還是另有隱情瓜贾,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布携悯,位于F島的核電站,受9級(jí)特大地震影響筷笨,放射性物質(zhì)發(fā)生泄漏憔鬼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一胃夏、第九天 我趴在偏房一處隱蔽的房頂上張望轴或。 院中可真熱鬧,春花似錦仰禀、人聲如沸照雁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)饺蚊。三九已至,卻和暖如春悬嗓,著一層夾襖步出監(jiān)牢的瞬間污呼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工包竹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燕酷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓周瞎,卻偏偏與公主長(zhǎng)得像苗缩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子声诸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容