扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
如何分析EOS源码中的与资源管理,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
成都创新互联长期为上千客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为唐河企业提供专业的成都做网站、网站建设,唐河网站改版等技术服务。拥有10余年丰富建站经验和众多成功案例,为您定制开发。
0 前言
1 EOS资源管理包括哪些资源
EOS资源管理模块主要对以下资源进行管理:
带宽和磁盘(Bandwidth and Log Storage (Disk))
计算资源(Computation and Computational Backlog (CPU))
内存资源(State Storage (RAM))
交易数据在区块链网络传播时需要消耗带宽资源,在各节点进行持久化存储时需要消耗磁盘资源;交易在执行过程中会消耗CPU资源,后续节点需要replay区块时也会消耗CPU资源;交易总量增长过大和交易发生速度(频次)过快都是一种开销;EOS状态数据库(state db)存储应用层常访问的历史数据,如交易记录、账户余额等,这些需要消耗内存资源和磁盘资源。
2 为什么要对资源管理
EOS网络中的资源总是有限的,而交易处理又是资源敏感的,为避免资源滥用,必须对资源使用权限作出限制和管理,保障网络的正常运行。
3 Token与资源管理的关系
EOS的Token(通证)的引入,有以下功能:
配合实现资源管理,抵押的Token越多,可使用的资源越多;
奖励BP节点(增发);
创业团队初始融资手段;
业务系统价值流通(如智能合约中某个操作,需要由发起方向接收方转账,则可由转移其拥有的Token来实现)
需要使用EOS网络资源的人就需要抵押其拥有的EOS Token,进行诸如购买RAM、抵押Token换取CPU资源和带宽资源等操作。
相关接口和实现在eosio.system智能合约中,如果未加载该智能合约并调用相关接口,则账户的RAM、CPU和NET使用不做限制,但交易和区块限制仍然生效。
4 资源管理机制
4.1 概述
通过上图来分析EOS资源管理机制(从上而下分析),即在源码中如何实现:
资源包括RAM内存资源,计量单位为字节;CPU计算资源、计量单位为us微秒(即占用多长时间);NET带宽资源,计量单位为字节;DISK磁盘资源隐含在前述部分,未单独再处理;
在具体实现时,分为单个账户限制、单笔交易限制和单个区块限制三部分;
通过使用量和限制量对比来进行管理; RAM的使用只有累计的概念,即只要该账户(对交易中各Action进行签名授权的账户)RAM还有使用剩余即可,对单次交易RAM使用量不做限制; CPU和NET的使用分为单次和累计两部分,即不能超出单次限制也不能超出累计限制;
一些基础的限制数据,如单笔交易最大CPU限制150ms、单个区块最大带宽限制1M等,通过写死的源码常量、或者config.ini配置文件、或者set接口调用、或者每次交易时传参来确定;
部分常变的限制数据,如账户抵押token量,全网token抵押量,以及所有资源使用量,均在状态数据库中存储(状态数据库基于内存文件映射机制实现);主要包括四张表,第一张是账户使用量表usage_index,第二张是账户限制表limit_index,第三张是区块使用量表state_index,第四张是区块配置表config_index(表名已简写);
资源使用异常有很多中错误码,主要包括图中所示错误码,其中需要说明的是灰名单账户机制,其限制量略有区别。
在交易初始化时会对资源使用量进行计算,并做早期检查,超标则直接拒绝执行; 在交易执行完成时对账户限制、交易限制、区块限制进行检查; 在区块打包时更新资源累计使用量,并更新限制。
4.2 虚拟资源限制
虚拟资源限制(virtual resource limits)与CPU&NET资源累计使用量相关,是为了更好的利用资源而引入的,因为资源使用量在不同时间段有高有低。引入虚拟资源限制后,当前一时间段资源使用量低时,扩大虚拟资源限制,下一时间段则可以使用相对更多的资源,反之亦然。
如上图所示,区块CPU和NET限制结构定义一样:
target:预期的单个区块资源使用量;
max:单个区块资源使用限制;
periods:累计使用量计算时间周期,如区块使用量计算周期为1小时;
max_multiplier:空闲状态下最大的资源使用量限制扩大系数;
contract:缩小系数,虚拟资源限制缩小的步长;
expand:放大系数,虚拟资源 限制放大的步长。
每个区块在打包时,对其包含的所有交易总量进行计算,如果资源使用量超过预期值target,则用contract系数来缩小virtual_resource_limits,如果低于预期值target,则用expand系数来扩大virtual_resource_limits。
账户资源使用量限制只有在抵押了token的前提下才生效,其限制值会结合区块限制值和token抵押占比来计算。
4.3 累计使用量
累计使用量针对CPU和NET,RAM无此概念。
如上图所示,累计使用量包括三个概念:
last_ordinal:该交易的时间,源码中通过区块头中的时间(区块编号)来确定;
value_ex:当前计算周期periods内的资源使用平均值;
consumed:过去一个计算周期的平均值加上当前周期的使用总量。
需注意,源码中在实现时,周期是平滑过渡的而不是严格分割,即假设前一周期是[0s-100s],每0.5m出块,则下一周期为[0.5s-100.5s],下下一周期为[1s-101s]。
每笔交易的每个action都会进行累加。如果两个action同属一个区块,则直接累加总用量consumed,直接累加平均使用量value_ex;如果该action与前一个action不属于同一区块,则将该区块之前的一个周期的平均使用量value_ex计算出来并加上当前区块使用量赋值给consumed,而平均使用量有一个衰减的概念。
delta表示该action时间与上一笔action的时间差。可见,如果某账户频繁操作,其衰减系数decay会一直比较大,最终导致其value_ex衰减缓慢,且限制值会越来越小,从而较快的达到使用上限;而如果操作不频繁,则衰减变快,限制值越来越大,不容易达到使用上限。
5 源码详述
5.1 表数据结构说明
如上图所示,一共4张表,resource_limits_config_index为区块限制配置表,resource_limits_state_index为区块使用记录表,resource_limits_index为账户限制配置表,resource_usage_index为账户使用记录表。usage_accumulator为CPU&NET累计使用量结构体,被区块使用记录表和账户使用记录表使用。elastic_limit_parameters为区块限制结构体,被区块限制配置表使用。
5.1.1 账户限制配置表
5.1.2 账户使用记录表
5.1.3 区块限制配置表
5.1.4 区块使用记录表
5.2 表操作接口说明
上图表述了四张表被哪些接口访问。
5.2.1 账户限制相关方法
set_account_limits:设置账户的内存、CPU、带宽权重;不需要修改的部分可通过get_account_limits获取再传入;
get_account_limits:获取账户的内存、CPU、带宽权重; 诸如购买内存、抵押CPU、带宽等等外部接口,最后都是调用这两个内部方法。
get_account_cpu_limit_ex:获取账户CPU限制(总限制、已使用、剩余量),该方法通过查询区块虚拟资源限制值,再查询账户权重和全网权重从而得到使用比例,最后得出实际限制值;
get_account_net_limit_ex:获取账户带宽限制(总限制、已使用、剩余量),与CPU同理;
get_account_cpu_limit:获取账户CPU剩余量,内部调用get_account_cpu_limit_ex;
get_account_net_limit:获取账户带宽剩余量,内部调用get_account_net_limit_ex;
5.2.2 账户使用相关方法
update_account_usage:标记账户使用了CPU和带宽资源;仅仅是标记作用,使用量为0,用以表明该账户这个时候发起了交易、申请了资源使用;在交易初始化时触发;即使后续交易失败,这一周期内也会有其使用记录,用于CPU和带宽累计使用量计算。
add_pending_ram_usage:增加账户内存使用量:创建账户、部署合约、修改权限等系统方法,以及其它智能合约接口需要操作状态数据库的都会调用该方法。
get_account_ram_usage:查询账户内存使用量。
verify_account_ram_usage:检查账户内存使用量是否超出限制。
add_transaction_usage:增加账户CPU和带宽使用量。
查询账户CPU和带宽使用量接口与查询账户CPU和带宽限制在一个接口中,见账户限制相关方法。
5.2.3 区块限制相关方法
set_block_parameters:设置区块CPU和带宽限制。
get_virtual_block_cpu_limit:查询区块虚拟CPU限制。
get_virtual_block_net_limit:查询区块虚拟带宽限制。
process_account_limit:生效账户权重和全网权重;例如账户CPU抵押量增大,则同步增大全网CPU抵押量。具体更新在set_account_limits交易时,生效则要等到区块打包时调用process_account_limit去生效。
5.2.4 区块使用记录表
get_block_cpu_limit:查询区块剩余CPU可用量,即限制值减去已使用量。
get_block_net_limit:查询区块剩余带宽可用量,即限制值减去已使用量。
process_block_usage:更新区块使用记录;在区块打包时调用。将当前区块使用量pending_net/cpu_usage统计到average_block_net/cpu_usage中,再根据当前区块使用量调整虚拟资源限制virtual_net/cpu_limit,最后重置pending_net/cpu_usage。
5.3 从数据角度分析
5.3.1 账户限制与使用
如上图所示:
在创建系统核心账户和其它账户时,CREATE了该账户的限制配置记录,默认CPU、带宽和内存限制均为-1,表示不做限制;
在eosio.bios智能合约中提供了一个接口setalimits来设置账户权重,在eosio.system智能合约中提供了购买内存(buyram)、出售内存(sellram)、抵押CPU和带宽(delegatebw)、赎回CPU和带宽(undelegatebw)等接口来SET账户权重;
刚修改的账户权重在当前区块打包前不生效,区块打包完成后才生效。
在发送交易时调用相关GET接口对交易授权者账户限制进行查询。
以上为账户限制相关流程,下面分析账户使用相关流程:
EOS账户有其它已存在账户代为创建,创建账户时,创建者需要消耗内存、CPU和带宽;被创建账号不消耗资源,账户被创建时CREATE一条使用记录,默认使用值为0。
在该账户授权进行交易时,调用相关接口SET账户使用量。
在该账户授权进行交易时,调用相关接口GET账户使用量。
5.3.2 区块限制使用
如上图所示(绿色为主要操作入口,蓝色为API查询接口):
链初始化时,CREATE了区块限制记录。区块CPU最大限制为200ms,不超过500ms的一半。只有该节点自己处理的交易需要记录其资源消耗,其它节点广播过来的交易不记录资源消耗,可以理解为一个区块自己有200ms在处理交易,其余时间等待其它节点同步交易(此逻辑尚不确定,需要进一步研究)。每笔交易最少CPU消耗为100us。区块带宽最大限制为1M。这样的设计,是假设单笔交易耗时100us,消耗带宽200字节的情况下,TPS能够达到1万(1秒2个区块500ms/100us=1万,1秒2个区块1M/200bytes>1万)。区块使用量累计周期为1小时。账户使用量累计周期为24小时。
在区块打包时会SET区块限制,但目前源码实现其值与默认值一样。
在交易初始化和交易打包时,会GET区块限制信息,通过区块虚拟资源限制(账户权重/全网权重来获取账户实际限制)。
在区块打包时,会GET区块限制信息,判断该区块资源使用是否超标。
部分对外API接口也会调用相关方法查询区块和账户限制。
上述为区块限制相关流程,下面分析区块使用相关流程:
区块使用表主要包括四大部分:周期内平均使用量、当前区块使用量、全网权重以及虚拟资源限制。
在链初始化时会CREATE并SET虚拟资源限制为区块配置表中的最大限制值cpu/net_limit_paramters.max。
在交易打包时会SET区块使用量,即将该区块中所有交易的使用量累加。
在区块打包时会SET区块周期内平均使用量、虚拟资源限制,并重置区块使用量。
部分对外API接口也会调用相关方法查询区块使用信息。
5.4 从流程角度分析
主要流程包括交易初始化(transaction_context::init)、交易执行(transaction_context::exec)、交易打包(transaction_context::finalize)、区块打包(controller_impl::finalize_block)。
5.4.1 交易初始化
交易初始化方法对该交易中所有action消耗的CPU和带宽总量进行计算,并计算CPU和带宽限制,并对CPU和带宽做基础检查。
本次交易带宽限制net_limit为当前区块最大限制减去当前区块已使用量;如果该限制太大,超过了单笔交易最大限制,则net_limit改为单笔交易最大限制;如果该笔交易额外配置了限制参数,且小于net_limit,则net_limit改为该限制参数值;
本次交易CPU限制同理;
检查本次交易已消耗的CPU(尚不清楚其逻辑,可能与延时交易相关);
标记相关账户已此时发送了交易,申请使用资源,用于计算累计使用量;
计算本次交易带宽和CPU使用量;
增加本次交易带宽使用量到局部变量net_usage中,并做检查;
检查本次交易是否超时。
5.4.2 交易执行
如上图所示,交易执行方法主要执行所有相关action,即智能合约中的接口,如果智能合约接口中有操作状态数据库的命令,则会改变其账户内存使用量记录。
5.4.3 交易打包
如上图所示,交易打包方法检查账户内存使用、CPU使用、带宽使用,检查区块带宽使用、CPU使用。
检查账户内存使用;
检查该区块带宽使用;
检查该区块CPU使用;
检查账户带宽和CPU使用,并将本次使用量累加到区块pending_usage中并检查。
5.4.4 区块打包
如上图所示,区块打包方法主要为:
使该区块内的修改账户资源使用权重结果生效;
修改区块限制,实际并未改变;
处理区块平均使用量、调整虚拟资源限制。如果该区块使用量超出预期target,则缩小限制值,反之扩大限制值。
看完上述内容,你们掌握如何分析EOS源码中的与资源管理的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流