前段时间终于试着复活了下EOSVotersTracker,过程艰辛
本文仅从该项目的需求来选择的,读者应按自己实际情况和应用来决定使用哪个~
EOSVotersTracker
在去年 6 月 EOS 主网刚启动,投票还未满足 15%抵押的时候,我出于对投票行为的好奇,于是想能不能提供一个工具来分析节点到底被谁投了,是什么导致了排名的变化,而且那会儿我们也在参与节点竞选。
对投票过程也很感兴趣。说干就干,大概 2 小时就写好了数据收集部分:
- 从第 1 个
block
开始遍历 - 从每个
block
中拿出voteproducer
相关对 action - 根据
action
对执行参数在内存中构建出投票关系 - 再提供 API 接口查询返回相应的信息
当然从现在来看,很多显然是欠缺考虑的。
比如说,与排名相关不仅仅只是投票角色的增减:
- stake 和 untake 都会造成投票权重的变化从而导致排名的变化
- 代理给 proxy 的投票人的 stake、untake,都会引起排名的变化
- 有些 stake 行为是作为 inline_action 被间接调用的
- EOS get_block 的 RPC 里是不包含 inline_action 的
- 投票人的权重会随着时间递减,相隔时间太久,重新 stake 会导致投票权重变大
再就是后来 block 越来越多,重来一次就要遍历从头到尾的 block 找出和投票相关的 action
以上的种种问题一直都存在,技术债越积越深
voters 内存表
后来没办法只能寻求更简便的办法,早在上线没多久就知道还有个 voters 表存储了所有选民的 stake 情况 vote_weight 情况。
后面就考虑:
- 能不能一直 dump 这个表的状态
- 通过 diff 每条数据的差异来得到投票人行为的变化
当时在本地节点测试了下:
- 20w 投票人,dump 出来5分钟左右
后来还没来得及继续完善,我们节点就关了,因为一直没拉到票~
eosinfra 社区代理 API
该 api 是对社区节点健康检查并进行负载均衡的一个服务。由 BlockMatrix 和 EOS ASIA 提供,此外他们还提供私有的部署服务 eosinfra.io
社区node一番测试下来,dump voters 表太慢了。。
EOSPark
提供免费key申请,测试了一下:
- 每个 key 并发上限 5
- 本机dump 还是蛮快
- api 和 eos 标准 api 差不多
测试下来:
- dump 50w voters 大概要 100 分钟
- 多申请几个 key 做负载均衡
- 应该能减少到 30 小时。
最后扔 aws 上才发现。。。该 api 部署的在国内阿里云。国外访问太慢了…
Dfuse
最后才看 dfuse,翻了一遍:
- 没找到 table_rows 的 api
- 只找到一个 websocket stream table rows 的 Api
测了一下:
- 能实时监听表的变化
- 但是设了 fetch:true 之后,很长时间没有返回
正当我准备放弃的时候,又扫了一遍 rest api.
- 发现一个 state/table 的接口
抱着试试看的心态调用了下,很快就返回了 50w voters 接近 120mb 的 snapshot 数据及截止到什么位置的 block number。
那么到这里基本上:
- 可以先 websokcket stream 监听最新的变化
- 再用 state API 获取最新的 snapshot
- 遍历 snapshot 之后再遍历 stream 的变化
- 通过 stream 的变化来 diff 和之前 row 的变化来
- 得到一个投票行为的变化
Redis
之前在 node 里用内存来存储关系,在后面看来还是很乱。
吸取教训后,决定还是用 redis 来存储。
毕竟 redis 的有序集合还是很适合来存储投票关系的。
- 启动前清空 redis
- 利用 snapshot 拿到的数据写入到 redis
- 再根据 stream 拿到的变化来比对 redis 里的状态得到一个 change
- 提供 api 查询这些 change
缺点
dfuse 虽然好用但他是一个非标的 API,倘若某天他倒闭了那么也就。。。
到时候再说吧,毕竟走 dump rows 也是可取的。只是有延迟而已!