此文主要对官方fabric-samples/high-throughtput 示例readme进行翻译,并填好在部署中遇到的坑。
原文地址high-throughput
话不多说,开始吧。
目的
该网络用于理解当需要每秒有上千个交易同时更新链上的同一个资产的时候,怎么样设计链码数据模型才是最合适的。一个简单的实现就是使用一个单键来代表资产,当交易到来时链码每次都尝试去更新这个键。然而当很多交易同时到来的时候,一个交易在peer节点上模拟和提交到账本这个时间段之间的时候,可能另一个交易已经更新这个相同的键了。这样在这个简单实现里,read-set的版本与orderer节点上的版本将不匹配,将会有大量的并发交易失败。为了解决这个问题,频繁更新的值被设计成一系列的增值,当需要检索这个值时,就把这些增值汇总。在这种方式下,不再频繁读取和更新单个行,而是考虑行集合。
使用案例
暂时就不翻译这块了,有需要的自己去官网上看,差不多就是用了比特币的UTXO方案。
如何做
这个示例提供了运行一个高吞吐量程序的链码和脚本。为了方便使用,它使用了fabric-samples/first-network文件夹下byfn.sh脚本启动的网络,只需要做一些小小的修改。
运行网络
1、cd到first-network文件夹,例如cd ~/fabric-samples/first-network。
2、用你最喜欢的编译器打开docker-compose-cli.yaml,编辑下列的行
1>在cli容器的volumes区域中,编译第二行修改链码的文件夹位置,例如:
./../chaincode/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
--> ./../high-throughput/chaincode/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
2>还是在volumes区域,编译第四行修改脚本的文件夹位置,例如:
./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
--> ./../high-throughput/scripts/:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
3>在脚本byfn.sh中注释掉docker exec cli scripts/script.sh这行,在这行前面加个#号
# docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE
3、现在就可以启动网络了,执行 ./byfn.sh -m up -c mychannel
4、打开一个新的终端窗口,执行docker exec -it cli bash 以下的所有操作都是在这个窗口上执行的。
安装和实例化链码
1、在cli容器里,执行 cd scripts 进入scripts文件夹
2、设置环境变量,执行 source setclienv.sh
3、建立通道和锚节点,执行./channel-setup.sh
4、安装链码,执行 ./install-chaincode.sh 1.0 。这个唯一的参数就是链码的版本号,你要升级和安装一个新的链码只要简单地增加这个版本号,例如 ./install-chaincode.sh 2.0 。
5、实例化链码,执行 ./instantiate-chaincode.sh 1.0 。这个版本号要和你安装的链码的版本号对应才行,未来你要升级到新版本就执行./upgrade-chaincode.sh 2.0 来代替 ./instantiate-chaincode.sh 1.0 。
6、链码已经安装成功了,可以接受调用交易啦!
调用链码
所有的调用都作为脚本在scripts文件夹里提供,具体如下
更新
更新命令的格式是./update-invoke.sh name value operation。operation可以选择+或者-,对应就是对值进行加或者减
例如:./update-invoke.sh myvar 100 +
获取
获取命令的格式是./get-invoke.sh name。name就是你要获取的变量名
例如:./get-invoke.sh myvar
删除
删除命令的格式是./delete-invoke.sh name。name就是你要删除的变量名
例如:./delete-invoke.sh myvar
清理(Prune)
清理将为一个变量所生成的所有增量合并成一行,删除所有的之前的行。这有助于当更新很多时清理账本。有两种类型的清理:prunefast和prunesafe。快速清理同时执行删除和聚合,因此如果在执行过程中发生错误,数据完整性就得不到保证。安全清理首先执行聚合,备份结果,然后再执行删除。这样的话如果中途发生错误,就可以保证数据的完整性。
清理命令的格式是./[prunesafe|prunefast]-invoke.sh name。name就是你要清理的变量名
例如:./prunefast-invoke.sh myvar 或者
./prunesafe-invoke.sh myvar
测试网络
提供了两个脚本来展示当同时运行多个并行的交易时这个系统的优势:many-updates.sh 和 many-updates-traditional.sh。第一个脚本接受和update-invoke.sh相同的参数,但是会并行地重复调用1000次。因此,最终的值就是给定的值乘以1000。运行此脚本确认您的网络正常运行。您可以通过检查peer和orderer的日志,并验证没有因为不正确的版本而拒绝调用来确定网站是否正常运行。
第二个脚本many-updates-traditional.sh也是发送1000个交易,但是使用的是传统的存储系统。它将会在账本中更新一个单行1000次,每次增加一个值(假如第一次调用设置为0,最后一次为1000)。期望是这一行的最终值为999.但是,每次运行此脚本时最终值都会更改,您可以在peer和orderer的日志里查看错误。
还有另一个脚本get-traditional.sh,用传统的方式获取一行的值,而没有用增量。
例如:./many-updates.sh testvar 100 +,执行后通过./get-invoke.sh获取的值应该是100000,执行./many-updates-traditional.sh testvar,再执行./get-traditional.sh testvar得到的结果应该是is undefined。
填坑
执行./channel-setup.sh 时有可能会遇到如下错误
这是因为端口的问题,byfn.sh启动的端口是7051-10051,需要修改channel-setup.sh脚本里的端口
执行./install-chaincode.sh脚本时如果遇到同样的问题同理。