前段时间终于试着复活了下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 也是可取的。只是有延迟而已!