如何分析EOS源碼中的與資源管理,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
成都創(chuàng)新互聯(lián)長(zhǎng)期為上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為唐河企業(yè)提供專業(yè)的成都做網(wǎng)站、網(wǎng)站建設(shè),唐河網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
0 前言
1 EOS資源管理包括哪些資源
EOS資源管理模塊主要對(duì)以下資源進(jìn)行管理:
帶寬和磁盤(Bandwidth and Log Storage (Disk))
計(jì)算資源(Computation and Computational Backlog (CPU))
內(nèi)存資源(State Storage (RAM))
交易數(shù)據(jù)在區(qū)塊鏈網(wǎng)絡(luò)傳播時(shí)需要消耗帶寬資源,在各節(jié)點(diǎn)進(jìn)行持久化存儲(chǔ)時(shí)需要消耗磁盤資源;交易在執(zhí)行過程中會(huì)消耗CPU資源,后續(xù)節(jié)點(diǎn)需要replay區(qū)塊時(shí)也會(huì)消耗CPU資源;交易總量增長(zhǎng)過大和交易發(fā)生速度(頻次)過快都是一種開銷;EOS狀態(tài)數(shù)據(jù)庫(state db)存儲(chǔ)應(yīng)用層常訪問的歷史數(shù)據(jù),如交易記錄、賬戶余額等,這些需要消耗內(nèi)存資源和磁盤資源。
2 為什么要對(duì)資源管理
EOS網(wǎng)絡(luò)中的資源總是有限的,而交易處理又是資源敏感的,為避免資源濫用,必須對(duì)資源使用權(quán)限作出限制和管理,保障網(wǎng)絡(luò)的正常運(yùn)行。
3 Token與資源管理的關(guān)系
EOS的Token(通證)的引入,有以下功能:
配合實(shí)現(xiàn)資源管理,抵押的Token越多,可使用的資源越多;
獎(jiǎng)勵(lì)BP節(jié)點(diǎn)(增發(fā));
創(chuàng)業(yè)團(tuán)隊(duì)初始融資手段;
業(yè)務(wù)系統(tǒng)價(jià)值流通(如智能合約中某個(gè)操作,需要由發(fā)起方向接收方轉(zhuǎn)賬,則可由轉(zhuǎn)移其擁有的Token來實(shí)現(xiàn))
需要使用EOS網(wǎng)絡(luò)資源的人就需要抵押其擁有的EOS Token,進(jìn)行諸如購買RAM、抵押Token換取CPU資源和帶寬資源等操作。
相關(guān)接口和實(shí)現(xiàn)在eosio.system智能合約中,如果未加載該智能合約并調(diào)用相關(guān)接口,則賬戶的RAM、CPU和NET使用不做限制,但交易和區(qū)塊限制仍然生效。
4 資源管理機(jī)制
4.1 概述

通過上圖來分析EOS資源管理機(jī)制(從上而下分析),即在源碼中如何實(shí)現(xiàn):
資源包括RAM內(nèi)存資源,計(jì)量單位為字節(jié);CPU計(jì)算資源、計(jì)量單位為us微秒(即占用多長(zhǎng)時(shí)間);NET帶寬資源,計(jì)量單位為字節(jié);DISK磁盤資源隱含在前述部分,未單獨(dú)再處理;
在具體實(shí)現(xiàn)時(shí),分為單個(gè)賬戶限制、單筆交易限制和單個(gè)區(qū)塊限制三部分;
通過使用量和限制量對(duì)比來進(jìn)行管理; RAM的使用只有累計(jì)的概念,即只要該賬戶(對(duì)交易中各Action進(jìn)行簽名授權(quán)的賬戶)RAM還有使用剩余即可,對(duì)單次交易R(shí)AM使用量不做限制; CPU和NET的使用分為單次和累計(jì)兩部分,即不能超出單次限制也不能超出累計(jì)限制;
一些基礎(chǔ)的限制數(shù)據(jù),如單筆交易最大CPU限制150ms、單個(gè)區(qū)塊最大帶寬限制1M等,通過寫死的源碼常量、或者config.ini配置文件、或者set接口調(diào)用、或者每次交易時(shí)傳參來確定;
部分常變的限制數(shù)據(jù),如賬戶抵押token量,全網(wǎng)token抵押量,以及所有資源使用量,均在狀態(tài)數(shù)據(jù)庫中存儲(chǔ)(狀態(tài)數(shù)據(jù)庫基于內(nèi)存文件映射機(jī)制實(shí)現(xiàn));主要包括四張表,第一張是賬戶使用量表usage_index,第二張是賬戶限制表limit_index,第三張是區(qū)塊使用量表state_index,第四張是區(qū)塊配置表config_index(表名已簡(jiǎn)寫);
資源使用異常有很多中錯(cuò)誤碼,主要包括圖中所示錯(cuò)誤碼,其中需要說明的是灰名單賬戶機(jī)制,其限制量略有區(qū)別。
在交易初始化時(shí)會(huì)對(duì)資源使用量進(jìn)行計(jì)算,并做早期檢查,超標(biāo)則直接拒絕執(zhí)行; 在交易執(zhí)行完成時(shí)對(duì)賬戶限制、交易限制、區(qū)塊限制進(jìn)行檢查; 在區(qū)塊打包時(shí)更新資源累計(jì)使用量,并更新限制。
4.2 虛擬資源限制
虛擬資源限制(virtual resource limits)與CPU&NET資源累計(jì)使用量相關(guān),是為了更好的利用資源而引入的,因?yàn)橘Y源使用量在不同時(shí)間段有高有低。引入虛擬資源限制后,當(dāng)前一時(shí)間段資源使用量低時(shí),擴(kuò)大虛擬資源限制,下一時(shí)間段則可以使用相對(duì)更多的資源,反之亦然。

如上圖所示,區(qū)塊CPU和NET限制結(jié)構(gòu)定義一樣:
target:預(yù)期的單個(gè)區(qū)塊資源使用量;
max:?jiǎn)蝹€(gè)區(qū)塊資源使用限制;
periods:累計(jì)使用量計(jì)算時(shí)間周期,如區(qū)塊使用量計(jì)算周期為1小時(shí);
max_multiplier:空閑狀態(tài)下最大的資源使用量限制擴(kuò)大系數(shù);
contract:縮小系數(shù),虛擬資源限制縮小的步長(zhǎng);
expand:放大系數(shù),虛擬資源 限制放大的步長(zhǎng)。
每個(gè)區(qū)塊在打包時(shí),對(duì)其包含的所有交易總量進(jìn)行計(jì)算,如果資源使用量超過預(yù)期值target,則用contract系數(shù)來縮小virtual_resource_limits,如果低于預(yù)期值target,則用expand系數(shù)來擴(kuò)大virtual_resource_limits。

賬戶資源使用量限制只有在抵押了token的前提下才生效,其限制值會(huì)結(jié)合區(qū)塊限制值和token抵押占比來計(jì)算。
4.3 累計(jì)使用量
累計(jì)使用量針對(duì)CPU和NET,RAM無此概念。

如上圖所示,累計(jì)使用量包括三個(gè)概念:
last_ordinal:該交易的時(shí)間,源碼中通過區(qū)塊頭中的時(shí)間(區(qū)塊編號(hào))來確定;
value_ex:當(dāng)前計(jì)算周期periods內(nèi)的資源使用平均值;
consumed:過去一個(gè)計(jì)算周期的平均值加上當(dāng)前周期的使用總量。
需注意,源碼中在實(shí)現(xiàn)時(shí),周期是平滑過渡的而不是嚴(yán)格分割,即假設(shè)前一周期是[0s-100s],每0.5m出塊,則下一周期為[0.5s-100.5s],下下一周期為[1s-101s]。
每筆交易的每個(gè)action都會(huì)進(jìn)行累加。如果兩個(gè)action同屬一個(gè)區(qū)塊,則直接累加總用量consumed,直接累加平均使用量value_ex;如果該action與前一個(gè)action不屬于同一區(qū)塊,則將該區(qū)塊之前的一個(gè)周期的平均使用量value_ex計(jì)算出來并加上當(dāng)前區(qū)塊使用量賦值給consumed,而平均使用量有一個(gè)衰減的概念。

delta表示該action時(shí)間與上一筆action的時(shí)間差。可見,如果某賬戶頻繁操作,其衰減系數(shù)decay會(huì)一直比較大,最終導(dǎo)致其value_ex衰減緩慢,且限制值會(huì)越來越小,從而較快的達(dá)到使用上限;而如果操作不頻繁,則衰減變快,限制值越來越大,不容易達(dá)到使用上限。
5 源碼詳述
5.1 表數(shù)據(jù)結(jié)構(gòu)說明

如上圖所示,一共4張表,resource_limits_config_index為區(qū)塊限制配置表,resource_limits_state_index為區(qū)塊使用記錄表,resource_limits_index為賬戶限制配置表,resource_usage_index為賬戶使用記錄表。usage_accumulator為CPU&NET累計(jì)使用量結(jié)構(gòu)體,被區(qū)塊使用記錄表和賬戶使用記錄表使用。elastic_limit_parameters為區(qū)塊限制結(jié)構(gòu)體,被區(qū)塊限制配置表使用。
5.1.1 賬戶限制配置表

5.1.2 賬戶使用記錄表

5.1.3 區(qū)塊限制配置表

5.1.4 區(qū)塊使用記錄表

5.2 表操作接口說明

上圖表述了四張表被哪些接口訪問。
5.2.1 賬戶限制相關(guān)方法
set_account_limits:設(shè)置賬戶的內(nèi)存、CPU、帶寬權(quán)重;不需要修改的部分可通過get_account_limits獲取再傳入;
get_account_limits:獲取賬戶的內(nèi)存、CPU、帶寬權(quán)重; 諸如購買內(nèi)存、抵押CPU、帶寬等等外部接口,最后都是調(diào)用這兩個(gè)內(nèi)部方法。
get_account_cpu_limit_ex:獲取賬戶CPU限制(總限制、已使用、剩余量),該方法通過查詢區(qū)塊虛擬資源限制值,再查詢賬戶權(quán)重和全網(wǎng)權(quán)重從而得到使用比例,最后得出實(shí)際限制值;
get_account_net_limit_ex:獲取賬戶帶寬限制(總限制、已使用、剩余量),與CPU同理;
get_account_cpu_limit:獲取賬戶CPU剩余量,內(nèi)部調(diào)用get_account_cpu_limit_ex;
get_account_net_limit:獲取賬戶帶寬剩余量,內(nèi)部調(diào)用get_account_net_limit_ex;
5.2.2 賬戶使用相關(guān)方法
update_account_usage:標(biāo)記賬戶使用了CPU和帶寬資源;僅僅是標(biāo)記作用,使用量為0,用以表明該賬戶這個(gè)時(shí)候發(fā)起了交易、申請(qǐng)了資源使用;在交易初始化時(shí)觸發(fā);即使后續(xù)交易失敗,這一周期內(nèi)也會(huì)有其使用記錄,用于CPU和帶寬累計(jì)使用量計(jì)算。
add_pending_ram_usage:增加賬戶內(nèi)存使用量:創(chuàng)建賬戶、部署合約、修改權(quán)限等系統(tǒng)方法,以及其它智能合約接口需要操作狀態(tài)數(shù)據(jù)庫的都會(huì)調(diào)用該方法。
get_account_ram_usage:查詢賬戶內(nèi)存使用量。
verify_account_ram_usage:檢查賬戶內(nèi)存使用量是否超出限制。
add_transaction_usage:增加賬戶CPU和帶寬使用量。
查詢賬戶CPU和帶寬使用量接口與查詢賬戶CPU和帶寬限制在一個(gè)接口中,見賬戶限制相關(guān)方法。
5.2.3 區(qū)塊限制相關(guān)方法
set_block_parameters:設(shè)置區(qū)塊CPU和帶寬限制。
get_virtual_block_cpu_limit:查詢區(qū)塊虛擬CPU限制。
get_virtual_block_net_limit:查詢區(qū)塊虛擬帶寬限制。
process_account_limit:生效賬戶權(quán)重和全網(wǎng)權(quán)重;例如賬戶CPU抵押量增大,則同步增大全網(wǎng)CPU抵押量。具體更新在set_account_limits交易時(shí),生效則要等到區(qū)塊打包時(shí)調(diào)用process_account_limit去生效。
5.2.4 區(qū)塊使用記錄表
get_block_cpu_limit:查詢區(qū)塊剩余CPU可用量,即限制值減去已使用量。
get_block_net_limit:查詢區(qū)塊剩余帶寬可用量,即限制值減去已使用量。
process_block_usage:更新區(qū)塊使用記錄;在區(qū)塊打包時(shí)調(diào)用。將當(dāng)前區(qū)塊使用量pending_net/cpu_usage統(tǒng)計(jì)到average_block_net/cpu_usage中,再根據(jù)當(dāng)前區(qū)塊使用量調(diào)整虛擬資源限制virtual_net/cpu_limit,最后重置pending_net/cpu_usage。
5.3 從數(shù)據(jù)角度分析
5.3.1 賬戶限制與使用

如上圖所示:
在創(chuàng)建系統(tǒng)核心賬戶和其它賬戶時(shí),CREATE了該賬戶的限制配置記錄,默認(rèn)CPU、帶寬和內(nèi)存限制均為-1,表示不做限制;
在eosio.bios智能合約中提供了一個(gè)接口setalimits來設(shè)置賬戶權(quán)重,在eosio.system智能合約中提供了購買內(nèi)存(buyram)、出售內(nèi)存(sellram)、抵押CPU和帶寬(delegatebw)、贖回CPU和帶寬(undelegatebw)等接口來SET賬戶權(quán)重;
剛修改的賬戶權(quán)重在當(dāng)前區(qū)塊打包前不生效,區(qū)塊打包完成后才生效。
在發(fā)送交易時(shí)調(diào)用相關(guān)GET接口對(duì)交易授權(quán)者賬戶限制進(jìn)行查詢。
以上為賬戶限制相關(guān)流程,下面分析賬戶使用相關(guān)流程:
EOS賬戶有其它已存在賬戶代為創(chuàng)建,創(chuàng)建賬戶時(shí),創(chuàng)建者需要消耗內(nèi)存、CPU和帶寬;被創(chuàng)建賬號(hào)不消耗資源,賬戶被創(chuàng)建時(shí)CREATE一條使用記錄,默認(rèn)使用值為0。
在該賬戶授權(quán)進(jìn)行交易時(shí),調(diào)用相關(guān)接口SET賬戶使用量。
在該賬戶授權(quán)進(jìn)行交易時(shí),調(diào)用相關(guān)接口GET賬戶使用量。
5.3.2 區(qū)塊限制使用

如上圖所示(綠色為主要操作入口,藍(lán)色為API查詢接口):
鏈初始化時(shí),CREATE了區(qū)塊限制記錄。區(qū)塊CPU最大限制為200ms,不超過500ms的一半。只有該節(jié)點(diǎn)自己處理的交易需要記錄其資源消耗,其它節(jié)點(diǎn)廣播過來的交易不記錄資源消耗,可以理解為一個(gè)區(qū)塊自己有200ms在處理交易,其余時(shí)間等待其它節(jié)點(diǎn)同步交易(此邏輯尚不確定,需要進(jìn)一步研究)。每筆交易最少CPU消耗為100us。區(qū)塊帶寬最大限制為1M。這樣的設(shè)計(jì),是假設(shè)單筆交易耗時(shí)100us,消耗帶寬200字節(jié)的情況下,TPS能夠達(dá)到1萬(1秒2個(gè)區(qū)塊500ms/100us=1萬,1秒2個(gè)區(qū)塊1M/200bytes>1萬)。區(qū)塊使用量累計(jì)周期為1小時(shí)。賬戶使用量累計(jì)周期為24小時(shí)。
在區(qū)塊打包時(shí)會(huì)SET區(qū)塊限制,但目前源碼實(shí)現(xiàn)其值與默認(rèn)值一樣。
在交易初始化和交易打包時(shí),會(huì)GET區(qū)塊限制信息,通過區(qū)塊虛擬資源限制(賬戶權(quán)重/全網(wǎng)權(quán)重來獲取賬戶實(shí)際限制)。
在區(qū)塊打包時(shí),會(huì)GET區(qū)塊限制信息,判斷該區(qū)塊資源使用是否超標(biāo)。
部分對(duì)外API接口也會(huì)調(diào)用相關(guān)方法查詢區(qū)塊和賬戶限制。
上述為區(qū)塊限制相關(guān)流程,下面分析區(qū)塊使用相關(guān)流程:
區(qū)塊使用表主要包括四大部分:周期內(nèi)平均使用量、當(dāng)前區(qū)塊使用量、全網(wǎng)權(quán)重以及虛擬資源限制。
在鏈初始化時(shí)會(huì)CREATE并SET虛擬資源限制為區(qū)塊配置表中的最大限制值cpu/net_limit_paramters.max。
在交易打包時(shí)會(huì)SET區(qū)塊使用量,即將該區(qū)塊中所有交易的使用量累加。
在區(qū)塊打包時(shí)會(huì)SET區(qū)塊周期內(nèi)平均使用量、虛擬資源限制,并重置區(qū)塊使用量。
部分對(duì)外API接口也會(huì)調(diào)用相關(guān)方法查詢區(qū)塊使用信息。
5.4 從流程角度分析
主要流程包括交易初始化(transaction_context::init)、交易執(zhí)行(transaction_context::exec)、交易打包(transaction_context::finalize)、區(qū)塊打包(controller_impl::finalize_block)。
5.4.1 交易初始化

交易初始化方法對(duì)該交易中所有action消耗的CPU和帶寬總量進(jìn)行計(jì)算,并計(jì)算CPU和帶寬限制,并對(duì)CPU和帶寬做基礎(chǔ)檢查。
本次交易帶寬限制net_limit為當(dāng)前區(qū)塊最大限制減去當(dāng)前區(qū)塊已使用量;如果該限制太大,超過了單筆交易最大限制,則net_limit改為單筆交易最大限制;如果該筆交易額外配置了限制參數(shù),且小于net_limit,則net_limit改為該限制參數(shù)值;
本次交易CPU限制同理;
檢查本次交易已消耗的CPU(尚不清楚其邏輯,可能與延時(shí)交易相關(guān));
標(biāo)記相關(guān)賬戶已此時(shí)發(fā)送了交易,申請(qǐng)使用資源,用于計(jì)算累計(jì)使用量;
計(jì)算本次交易帶寬和CPU使用量;
增加本次交易帶寬使用量到局部變量net_usage中,并做檢查;
檢查本次交易是否超時(shí)。
5.4.2 交易執(zhí)行

如上圖所示,交易執(zhí)行方法主要執(zhí)行所有相關(guān)action,即智能合約中的接口,如果智能合約接口中有操作狀態(tài)數(shù)據(jù)庫的命令,則會(huì)改變其賬戶內(nèi)存使用量記錄。
5.4.3 交易打包

如上圖所示,交易打包方法檢查賬戶內(nèi)存使用、CPU使用、帶寬使用,檢查區(qū)塊帶寬使用、CPU使用。
檢查賬戶內(nèi)存使用;
檢查該區(qū)塊帶寬使用;
檢查該區(qū)塊CPU使用;
檢查賬戶帶寬和CPU使用,并將本次使用量累加到區(qū)塊pending_usage中并檢查。
5.4.4 區(qū)塊打包

如上圖所示,區(qū)塊打包方法主要為:
使該區(qū)塊內(nèi)的修改賬戶資源使用權(quán)重結(jié)果生效;
修改區(qū)塊限制,實(shí)際并未改變;
處理區(qū)塊平均使用量、調(diào)整虛擬資源限制。如果該區(qū)塊使用量超出預(yù)期target,則縮小限制值,反之?dāng)U大限制值。
看完上述內(nèi)容,你們掌握如何分析EOS源碼中的與資源管理的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
網(wǎng)站欄目:如何分析EOS源碼中的與資源管理
文章分享:http://www.chinadenli.net/article40/iigoho.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、外貿(mào)建站、用戶體驗(yàn)、虛擬主機(jī)、服務(wù)器托管、定制開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)