Fabric基础

Fabric交易流程图

  • SDK 生成 Proposal,其中包含调用链码的相关参数等信息。
  • SDK 将 Proposal 发送到多个不同的 peer 节点。
    • peer 根据 Proposal 的信息,调用用户上传的链码。
    • 链码处理请求,将请求转换为对账本的读集合和写集合。
    • peer 对读集合和写集合进行签名,并将 ProposalResponse 返回给 SDK。
  • SDK 收到多个 peer 节点的 ProposalResponse,并将读集合与写集合和不同节点的签名拼接在一起,组成 Envelope。
  • SDK 将 Envelope 发送给 orderer 节点,并监听 peer 节点的块事件。
  • orderer 节点收到足够的 Envelope 后,生成新的区块,并将区块广播给所有 peer 节点。
  • 各个 peer 节点对收到区块进行验证,并向 SDK 发送新收到的区块和验证结果。
  • SDK 根据事件中的验证结果,判断交易是否成功上链。

存储结构

高性能


避免Key冲突

Fabric 会记录所有失败的交易记录,因此如果2笔交易,其中一笔修改了对应 Key 的值,导致版本发生变化,后面的交易对此 Key 的修改会导致交易失败。

大量的失败交易会降低 Fabric 整体的 TPS 指标,并且占用网络吞吐量。

在进行链码设计时,可以通过链码的逻辑设计,减少不同交易对同一个 Key 进行写入的频率。例如,在链码调用阶段,对同一个Key进行写入的多笔不同交易,应避免间隔过短,即避免对Key进行频繁写入。建议在对该Key的上一笔写入交易成功(即 commit 到账本)后再发起下一笔写入交易。

相关资料
high-throughput

减少 stub 读取和写入账本的次数

Fabric 中的链码与 peer 节点之间的通信与 SDK 和区块链节点的通信类似,也是通过 GRPC 来进行的。当在链码中调用查询、写入账本的接口时(例如 GetState、PutState 等),链码发送 GRPC 请求给 peer 节点,等待 peer 返回结果后再返回到链码的逻辑中。当链码在一次 Query/Invoke 中调用了多次账本的查询或写入接口时,会产生一定的网络通信成本和延迟,这对网络的整体吞吐率会有一定的影响。

比如:存储在 CouchDB 的数据,它是通过提供服务的方式获取数据,因此在获取数据的过程是,链码 —> Peer 节点 —-> CouchDB服务获取数据整体流程上会导致一定的网络开销。

我们在设计应用时,应尽量减少一次 Query/Invoke 中的查询和写入账本的次数。在一些对吞吐有很高要求的特殊场景下,可以在业务层对多个 Key 及对应的 Value 进行合并,将多次读写操作变成一次操作。

减少链码的运算量

当链码被调用时,会在 peer 的账本上挂一把读锁,保证链码在处理该笔交易时,账本的状态不发生改变,当新的区块产生时,peer 将账本完全锁住,直到完成账本状态的更新操作。如果我们的链码在处理交易时花费了大量时间,会让 peer 验证区块等待更长的时间,从而降低整体的吞吐量。

在编写链码时,链码中最好只包含简单的逻辑、校验等必要的运算,将不太重要的逻辑放到链码外进行。

使用SDK的 discovery 机制

因为在多个节点收集提案的响应是需要时间的,因此,根据背书策略,选择最小数量的背书数据即可,同时修改背书的超时时间,避免长时间等待单个节点的数据导致交易执行缓慢。

Fabric调试环境搭建

获取源码

  • 完成VScode、Docker、Go、Git等环境安装。
  • 拉取Ewkoll/fabric的代码到本地。
  • 切换到1.4.6分支。
  • 切换到shell目录执行./start.sh init
  • 目录
    • peer目录,用于发起通道创建,节点加入通道,链码安装、实例化等操作。
    • peer_government节点启动。
    • peer_public节点启动。
    • order排序节点启动。

此分支是使用ENV的方式实现本地启动节点,方便后续的代码调试。