EOS.IO中的插件布局

EOS.IO中的插件布局 | 源碼解讀

目的:
技術(shù)小白如果不小心打開(kāi)了本文,直接拖到最后看總結(jié)即可
本文的閱讀對(duì)象是對(duì)EOS源碼感興趣的同學(xué)
通過(guò)本文,你會(huì)掌握閱讀每一個(gè)插件的步驟

之前我們通過(guò)5行代碼對(duì)eosiod的脈絡(luò)有了大致的了解,我們知道了它是一個(gè)插件化的服務(wù),插件化服務(wù)的特點(diǎn)是可以像USB一樣即插即用,有著很高的靈活性。今天我們更深入一點(diǎn),來(lái)看下EOS服務(wù)的插件是如何布局的,以及如何閱讀每一個(gè)插件的代碼。

EOS.IO的每個(gè)插件,在生命期內(nèi)都會(huì)經(jīng)歷以下階段

  1. 插件注冊(cè)

  2. 插件初始化

  3. 插件啟動(dòng)

下面我們一一道來(lái)。

插件注冊(cè)

還記得上次我們說(shuō)過(guò)的最后一行代碼嗎?

image

這行代碼會(huì)把不同的插件注冊(cè)到管理插件的插件容器中,剛開(kāi)始,不是所有插件都會(huì)主動(dòng)把自己注冊(cè)到系統(tǒng)中,我們來(lái)看下在初始狀態(tài)下,有哪些插件會(huì)主動(dòng)注冊(cè)自己,如下圖:

image

可以看到,插件的命名很清晰,通過(guò)命名就可以判斷不同插件所具備的能力。例如producer_plugin肯定是和出塊節(jié)點(diǎn)相關(guān)的插件。

解決插件依賴

上一篇文章中,由于篇幅原因,我們跳過(guò)了注冊(cè)過(guò)程中的一行代碼:

plug->register_dependencies();

從字面來(lái)看,的作用是注冊(cè)所依賴插件,今天我們就從這行代碼開(kāi)始,它的實(shí)現(xiàn)如下所示:

image

它會(huì)調(diào)用每個(gè)插件的plugin_requires函數(shù),但詭異的是,沒(méi)有任何一個(gè)插件有這個(gè)函數(shù)的實(shí)現(xiàn),通過(guò)搜索發(fā)現(xiàn),這個(gè)函數(shù)是由一個(gè)宏來(lái)定義的:

image

猜想只要插件類中包含了APPBASE_PLUGIN_REQUIRES宏,即是定義了plugin_requires函數(shù),再查看不同插件中的頭文件,果不其然,注冊(cè)到系統(tǒng)中的插件都包含了該宏,下面是3個(gè)不同插件的例子

image

你一定發(fā)現(xiàn)了其中的差異,每個(gè)插件的參數(shù)是不同的,這是什么情況?此時(shí)就得看plugin_requires的具體的實(shí)現(xiàn)了

image

plugin_requires函數(shù)會(huì)調(diào)用boost庫(kù)中的一個(gè)宏——BOOST_PP_SEQ_FOR_EACH,該宏的用法參見(jiàn)http://t.cn/REqJmyG

在本例子中,意為對(duì)于PLUGINS中的每一個(gè)PLUGIN,都調(diào)用一次register_plugin<PLUGIN>();,如上圖所示。以net_api_plugin這個(gè)插件為例,下面是該插件的展開(kāi)式

image

清楚了吧,可以看到展開(kāi)后,對(duì)所依賴的每個(gè)插件,會(huì)繼續(xù)調(diào)用register_plugin,形成了遞歸效果,直到遇到獨(dú)立的插件為止,例如上面的chain_plugin就是一個(gè)獨(dú)立的插件。

翻譯為白話就是

在注冊(cè)一個(gè)插件之間,先把該插件所依賴的其他插件注冊(cè)到系統(tǒng)中。且無(wú)論依賴多少個(gè)插件,你只需要寫(xiě)一行代碼。

在我看來(lái),這樣的寫(xiě)法是非常優(yōu)雅的,設(shè)計(jì)上可以用精妙來(lái)形容,此時(shí),系統(tǒng)中的插件布局變成了這樣:

image

至此,插件的注冊(cè)部分就全部完成了,你可能已經(jīng)發(fā)現(xiàn)了,上述插件有重復(fù)注冊(cè)的情況,但不用擔(dān)心,register_plugin函數(shù)的實(shí)現(xiàn)會(huì)避免該情況的發(fā)生,如下:

image

插件初始化

注冊(cè)完插件后,下一步就需要對(duì)這些插件初始化,我們回到之前介紹的「第1行」代碼,該代碼的調(diào)用次序由上至下如下圖所示,

image

可以看到初始化是由initialize_impl這個(gè)函數(shù)實(shí)現(xiàn)的,這個(gè)函數(shù)接收命令行選項(xiàng),和3個(gè)自動(dòng)啟動(dòng)的插件作為參數(shù)——chain_pluginhttp_pluginnet_plugin(我用白色的下劃線做了標(biāo)記)。

initialize_impl做了2件事情:

  1. 獲取配置信息,包括命令行選項(xiàng)和配置文件中的參數(shù)

  2. 初始化插件

獲取配置信息這件事,EOS.IO也借助了boost庫(kù),對(duì)于該知識(shí)的說(shuō)明,你可以參考這篇文章:http://sina.lt/fpBy

值得說(shuō)明的事,為了產(chǎn)生不同插件的特定配置項(xiàng),每個(gè)插件都實(shí)現(xiàn)了set_program_options函數(shù),以http_plugin為例

image

上面代碼為http_plugin提供了外部參數(shù)http-server-address,該參數(shù)既可以通過(guò)命令行獲取(由plugin_cli_optsplugin_cfg_opts兩個(gè)變量控制),又可以通過(guò)配置文件獲取(由plugin_cfg_opts控制),于是,當(dāng)你在命令行輸入eosiod --help時(shí),會(huì)輸出以下信息

image

所有的參數(shù)信息最終會(huì)存儲(chǔ)在options這個(gè)變量中,然后在初始化時(shí),傳入不同的插件

image

配置信息獲取成功后,就該對(duì)插件進(jìn)行初始化了,需要對(duì)哪些插件初始化呢,來(lái)自3個(gè)途徑:

  1. 上文提到的自動(dòng)啟動(dòng)的插件

  2. 配置文件中描述的插件

  3. 1和2所依賴的插件

第1個(gè)途徑上面已經(jīng)介紹了,現(xiàn)在看下第2個(gè)途徑包含哪些插件,打開(kāi)config.ini文件,可以看到以下插件列表

image

最后,我們?cè)倏聪孪到y(tǒng)是如何初始化依賴插件的,在initialize_impl函數(shù)中,上述2個(gè)途徑的插件初始化都會(huì)調(diào)用initialize這個(gè)函數(shù),這個(gè)函數(shù)的實(shí)現(xiàn)如下所示

image

進(jìn)入initialize函數(shù),你發(fā)現(xiàn)了什么,plugin_requires這個(gè)函數(shù)是不是非常熟悉?沒(méi)錯(cuò),上文已經(jīng)花了大量的篇幅來(lái)解釋這個(gè)函數(shù),但在初始化場(chǎng)景下有什么不同呢?細(xì)心的你應(yīng)該發(fā)現(xiàn)了,差異在于Lambda表達(dá)式上,我們?cè)俅文?code>chain_api_plugin這個(gè)插件舉例,嘗試對(duì)其進(jìn)行展開(kāi)

image

看出變化了吧,意思是

如果這個(gè)插件依賴其他插件,則先對(duì)其依賴的插件調(diào)用initialize,這些插件如果還依賴另外的插件,則先對(duì)另外的插件調(diào)用initialize,依此遞歸下去……直到遇到獨(dú)立插件為止

待「依賴鏈」全部初始化完成后,該插件才會(huì)調(diào)用plugin_initialize對(duì)自己初始化,同樣,不同插件實(shí)現(xiàn)了不同的初始化方式。于是,插件的布局及初始化部分就已經(jīng)完成了。

不難發(fā)現(xiàn),插件的啟動(dòng)也是通過(guò)這種方式完成的,這一部分我就不展開(kāi)了,留給你作為作業(yè)吧:)

總結(jié)

本文主要分析了EOS.IO這個(gè)開(kāi)源軟件的插件布局,包括了插件在系統(tǒng)中的生命周期,同時(shí)我們也學(xué)習(xí)了一個(gè)非常Tricky的解依賴的編碼技巧,當(dāng)我第一次看到這樣的實(shí)現(xiàn)時(shí),我是這樣感嘆的:

eos里插件的設(shè)計(jì)都是鏈?zhǔn)降模獴T了

敲黑板了,通過(guò)以上內(nèi)容,你在今后學(xué)習(xí)每個(gè)插件時(shí),其實(shí)只需記住3個(gè)函數(shù)即可,它們是每個(gè)插件中的

  1. set_program_options:用來(lái)設(shè)置插件的參數(shù)

  2. plugin_initialize:實(shí)現(xiàn)了插件具體的初始化過(guò)程

  3. plugin_startup:運(yùn)行插件

免責(zé)聲明:以上所有代碼分析和對(duì)代碼的感受,都不構(gòu)成任何投資建議,謝謝

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,382評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,038評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,853評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,616評(píng)論 6 408
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,112評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,355評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,869評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,727評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,928評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,165評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,570評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,813評(píng)論 1 282
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,585評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,892評(píng)論 2 372

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