热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HyperledgerFabric外部链码构建与运行的开发笔记

本文介绍了HyperledgerFabric外部链码构建与运行的相关知识,包括在HyperledgerFabric2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Hyperledger Fabric外部链码构建与运行相关的知识,希望对你有一定的参考价值。



外部链码构建与运行

官方文档

在Hyperledger Fabric 2.0版本之前,链码的构建和运行是节点实现的一部分,并且定制化是困难的。所有链码在节点上实例化是通过”构建“即根据语言指定的逻辑在节点上硬编码。构建过程将生成Docker容器镜像作为客户端连接节点用来运行可执行的链码。

这种方法将链代码实现限制为只能使用几种语言实现,要求Docker成为部署环境的一部分,并阻止将链代码作为长时间运行的服务器进程运行。


外部构建模式

Hyperledger Fabric外部构建器和启动器大致基于Heroku Buildpacks。buildpack实现只是将程序归档转换为可以运行的程序或脚本的集合。buildpack模型已针对链码包进行了调整,并扩展为支持链码执行和发现。


外部构建和运行API

外部构建和运行由4个脚本程序组成:



  • bin/detect:确定是否应使用此buildpack来构建chaincode程序包并启动它

  • bin/build:转换链码包为可执行的链码

  • bin/release(可选):为peer节点提供关于链码的元数据

  • bin/run(可选):运行链码


bin/detect

bin/detect脚本决定是否应使用此buildpack来构建chaincode程序包并启动它,peer节点通过两个参数调用detect:

bin/detect CHAINCOD_SOURCE_DIR CHAINCODE_METADATA_DIR

detect被调用,CHAINCOD_SOURCE_DIR包含的链码资源以及CHAINCODE_METADATA_DIR包含的metadata.json文件将从链码包中安装到节点。CHAINCOD_SOURCE_DIRCHAINCODE_METADATA_DIR应该被作为只读输入。如果将buildpack应用于chaincode源程序包,detect必须返回退出码0;否则,其他任何退出代码都将指示buildpack不应用内于chaincode源程序包。

下面是一个简单的用于go语言链码的detect脚本例子:

#!/bin/bash
CHAINCODE_METADATA_DIR="$2"
# 使用jq工具从metadata.json中获取链码类型,如果链码类型为golang,则成功退出
if [ "$(jq -r .type "$CHAINCODE_METADATA_DIR/metadata.json" | tr '[:upper:]' '[:lower:]')" = "golang" ]; then
exit 0
fi
exit 1

bin/build

bin/build脚本用于构建,编译,或者转换链码包的内容到可以被releaserun使用的类型。节点通过三个参数调用build:

bin/build CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR BUILD_OUTPUT_DIR

build被调用,CHAINCOD_SOURCE_DIR包含的链码资源以及CHAINCODE_METADATA_DIR包含的metadata.json文件将从链码包中安装到节点。BUILD_OUTPUT_DIR是一个文件夹用于存放releaserun需要的文件。build脚本应该将CHAINCOD_SOURCE_DIRCHAINCODE_METADATA_DIR作为只读输入,BUILD_OUTPUT_DIR作为可写输出。

下面是一个简单的用于go语言链码的build脚本例子:

#!/bin/bash
CHAINCODE_SOURCE_DIR="$1"
CHAINCODE_METADATA_DIR="$2"
BUILD_OUTPUT_DIR="$3"
# 从 metadata.json获取包内容
GO_PACKAGE_PATH="$(jq -r .path "$CHAINCODE_METADATA_DIR/metadata.json")"
if [ -f "$CHAINCODE_SOURCE_DIR/src/go.mod" ]; then
cd "$CHAINCODE_SOURCE_DIR/src"
go build -v -mod=readonly -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
else
GO111MODULE=off go build -v -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
fi
# 存储状态数据库索引元数据提供给release
if [ -d "$CHAINCODE_SOURCE_DIR/META-INF" ]; then
cp -a "$CHAINCODE_SOURCE_DIR/META-INF" "$BUILD_OUTPUT_DIR/"
fi

bin/release

bin/release脚本为节点提供链码元数据。该脚本是可选的。如果没有提供,这一步将会跳过。节点通过两个参数调用release

bin/release BUILD_OUTPUT_DIR RELEASE_OUTPUT_DIR

调用release时,BUILD_OUTPUT_DIR包含构建程序填充的归档,应将其视为只读输入。RELEASE_OUTPUT_DIRrelease必须放置归档以供节点使用的目录。

release执行完成,节点将会从RELEASE_OUTPUT_DIR消费两种类型的元数据:



  • CouchDB定义的状态数据库索引。

  • 外部链码服务连接信息(chaincode/server/connection.json)

如果链码要求CouchDB索引定义,release需要将索引放置在RELEASE_OUTPUT_DIR下的state/couchdb/indexes文件夹内。索引必须含有.json扩展名。

在使用链码服务器实现的情况下,release负责使用链码服务器的地址以及与链码通信所需的任何TLS资产来填充chaincode/server/connection.json。将服务器连接信息提供给节点时,将不会调用run

下面是一个简单的用于go语言链码的release脚本例子:

#!/bin/bash
BUILD_OUTPUT_DIR="$1"
RELEASE_OUTPUT_DIR="$2"
# 从 META-INF/* 拷贝索引文件到输出文件夹
if [ -d "$BUILD_OUTPUT_DIR/META-INF" ] ; then
cp -a "$BUILD_OUTPUT_DIR/META-INF/"* "$RELEASE_OUTPUT_DIR/"
fi

bin/run

bin/run脚本用于链码的运行。节点通过两个参数调用run

bin/run BUILD_OUTPUT_DIR RUN_METADATA_DIR

BUILD_OUTPUT_DIR包含build程序填充的归档,而RUN_METADATA_DIR包含有一个名为chaincode.json的文件,该文件包含链码连接和注册到节点所需的信息,run将被调用。bin/run脚本对于BUILD_OUTPUT_DIR以及RUN_METADATA_DIR文件夹应为只读输入。chaincode.json文件包含的关键信息有:



  • chaincode_id:连接到链码包的唯一ID

  • peer_address:``peer节点的ChaincodeSupport中的gRPC服务端点主机地址,格式为host:port.

  • client_cert:peer生成的PEM编码的TLS客户端证书。当链码与节点建立连接时将会被使用。

  • client_key:peer生成的PEM编码的客户端秘钥。当链码与节点建立连接时将会被使用。

  • root_cert:peer节点的ChaincodeSupport中的gRPC服务端点主机使用的PEM编码的TLS根证书。

run停止时,与peer连接的链码也会终止。如果另一个请求访问链码,节点将会尝试通过调用run启动链码的另一个实例。在调用链码时,chaincode.json文件内容不能够被缓存。

下面是一个简单的用于go语言链码的run脚本例子:

#!/bin/bash
BUILD_OUTPUT_DIR="$1"
RUN_METADATA_DIR="$2"
# 为go语言链码shim包配置环境变量
export CORE_CHAINCODE_ID_NAME="$(jq -r .chaincode_id "$RUN_METADATA_DIR/chaincode.json")"
export CORE_PEER_TLS_ENABLED="true"
export CORE_TLS_CLIENT_CERT_FILE="$RUN_METADATA_DIR/client.crt"
export CORE_TLS_CLIENT_KEY_FILE="$RUN_METADATA_DIR/client.key"
export CORE_PEER_TLS_ROOTCERT_FILE="$RUN_METADATA_DIR/root.crt"
# 为go语言链码shim包获取秘钥和证书材料
jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_CERT_FILE"
jq -r .client_key "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_KEY_FILE"
jq -r .root_cert "$RUN_METADATA_DIR/chaincode.json" > "$CORE_PEER_TLS_ROOTCERT_FILE"
if [ -z "$(jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json")" ]; then
export CORE_PEER_TLS_ENABLED="false"
fi
# 执行链码并使用链码进程替代脚本
exec "$BUILD_OUTPUT_DIR/chaincode" -peer.address="$(jq -r .peer_address "$ARTIFACTS/chaincode.json")"

外部构建和运行的配置

core.yamlchaincode配置区域下添加一个externalBuilder元素配置节点以使用外部构建器.每一个外部构建器的定义必须包含名字(用于日志)和包含构建器脚本的bin文件夹的上一级路径。

调用外部构建器脚本时还可以从节点获取环境变量名称的可选列表。

下面的示例定义了两个外部构建器:

chaincode:
externalBuilders:
- name: my-golang-builder
path: /builders/golang
environmentWhitelist:
- GOPROXY
- GONOPROXY
- GOSUMDB
- GONOSUMDB
- name: noop-builder
path: /builders/binary

在这个示例中,实现的构建器my-golang-builder被包含在/builders/golang文件夹内,它的脚本文件位于/builders/golang/bin.当节点调用任何与my-golang-builder相关的构建脚本时,将只会传播白名单内的环境变量的值。

这些环境变量总是传播到外部构建器:



  • LD_LIBRARY_PATH

  • LIBPATH

  • PATH

  • TMPDIR

externalBuilder配置存在时,节点将会迭代按顺序排列的构建器的列表。调用/bin/detect直到其中的一个成功执行。

如果没有构建器成功执行detect脚本,节点将会回滚使用初始的Docker通过节点实现构建进程。这说明外部的构建器是完全可选的。

在上面的示例中,节点将试图使用my-golang-builder,如果无效的话则使用noop-builder,还是无效的话最后使用节点内部构建进程。


链码包

Fabric 2.0引入了新的生命周期链码。链码包的格式从序列号协议缓冲消息变为了由gzip压缩的POSIX tape归档。链码包通过使用peer lifecycle chaincode package创建新的格式。


Lifecycle链码包内容

lifecycle链码包包含两个文件,第一个文件code.tar.gz是一个使用gzip压缩的POSIX tape归档。这个文件包括链码的源归档。由节点CLI创建并将链码的实现源码放置在src文件夹下,链码的元数据(如CouchDB索引文件)放置在META-INF文件夹。

第二个文件metadata.json是一个JSON格式的文档包含三个键:



  • type:链码的类型(例如GOLANG,JAVA,NODE)

  • path:对于go语言链码,则是GOPATH或者GOMOD到主链码包的相对路径,其他类型的链码未定义。

  • label:用于生成包ID的链码标签,在新的链码lifecycle过程中用于标识包的身份。

typepath字段仅由Docker平台构建使用。


链码包以及外部构建器

当链码包安装在节点上后,code.tar.gzmetadata.json的内容将不能调用外部构建器处理。除了label字段用于新的lifecycle对包ID进行计算。为用户提供了很大的灵活性,使他们可以打包将由外部构建者和启动者处理的源和元数据。

例如,可以构造一个自定义的链码包,该代码包在code.tar.gz中包含一个预编译的链码实现,并带有一个metadata.json文件,允许二进制构建包检测该自定义包,验证哈希值并作为链码运行。

另一个示例是chaincode程序包,其中仅包含状态数据库索引定义以及外部启动程序连接到正在运行的chaincode服务器所需的数据。在这种情况下,build过程将仅从过程中提取元数据,然后将其release给节点。

唯一的要求是code.tar.gz只能包含常规文件和目录条目,并且这些条目不能包含会导致文件写入链码包根路径逻辑外。


推荐阅读
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
author-avatar
从1前2有3个4人_706
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有