------------------------------------------------------------- ==================================== > 技能 > 区块链 > 58区块链服务平台BaaS的设计与实践 区块链 是分布式数据存储、点对点传输、共识机制、加密算法、智能合约等计算机技术在互联网时代的创新应用模式。区块链 技术被认为是继大型机、个人电脑、互联网之后计算模式的颠覆式创新。
区块链 本身具有分布式(Distributed)、去中介(Disintermediation)、去信任(Trustless)、不可篡改(Immutable)等特性,因此区块链 天然适合用于解决数据不对称、数据孤岛、数据不可信等问题。业内普遍认为,区块链 在金融服务、供应链管理、文化娱乐、智能制造、社会公益、教育就业、生活服务等诸多领域都具备丰富的应用场景。
为落地区块链 技术与 58 集团业务的契合点,助力集团业务增长,58 区块链实验室基于区块链技术设计与研发了58 的区块链服务平台 ——58 BaaS ,提供一整套区块链部署、合约开发、实时监控、弹性伸缩等企业级区块链服务解决方案,通过低成本的快速构建区块链基础设施,加速58 集团业务创新,并将平台能力开放共享,共同推动区块链应用场景的落地,推动可信互联网的发展。
58 BaaS 的整体业务架构图如下:
区块链底层网络搭建
区块链底层网络的搭建经历了三个阶段:
第一阶段 ,开始为了快速部署区块链网络,打通整体流程,整个区块链网络的拓扑信息是在一个 yaml 文件中,通过 docker-compse 进行部署,背书节点、排序节点等所有节点都运行在一台服务器上。
第二阶段 ,为了将区块链网络部署分布式部署到多台服务器,手动对 yaml 文件进行拆分,比如区块链网络由两个组织组成,每个组织包含两个 Peer 节点,区块链网络中包括两个排序节点、四个 kafka 节点和三个 zookeeper 节点。手动拆分成 4 份 yaml 文件,部署到四台服务器上,并通过 Docker 原生的 Overlay 网络组建 Docker 集群进行通信。快速的为区块链业务提供了支撑。
随着区块链网络部署需求的增多,人工部署操作繁琐、易出错等问题越发突出,区块链网络的部署需要自动化。流程自动化的前提是部署的标准化,所以按照节点类型抽象出所有节点的 yaml 文件:peer.yaml、orderer.yaml、ca.yaml、kafka.yaml 和 zookeeper.yaml,如 peer.yaml:
services:
$:
container_name: $
environment:
– CORE_PEER_ID=$
– CORE_PEER_LOCALMSPID=$
…
ports:
– $:7051
– $:7052
另外,当前区块链网络的部署策略是,一个区块链网络部署一组 peer、orderer、kafka 和 zk 集群。随着区块链网络的增多,kafka 和 zk 节点的数量快速上升。每个区块链网络都创建一组 kafka 和 zk 的集群是否有必要,虽然具备了强隔离性,但造成了大量的资源浪费和维护成本。
考虑到区块链网络的性能瓶颈并不在这里,所以,搭建了一套独立的 Kafka 集群和 zk 集群,所有的区块链网络进行共用。但每个区块链网络都有一个默认的系统通道名 testchainid,而区块链网络的每个通道名都对应会创建一个 Kafka 主题,这样当多个区块链网络共用一个 kafka 集群后,系统通道主题就会冲突。解决办法是在创建创世区块的时候通过工具 configtxgen 的 channelID 参数指定系统通道名。
第三阶段 ,通过引入 kubernetes 集群来对区块链网络中所有的节点进行统一管理,包括进行节点的创建和维护、节点的状态、资源的监控和报警等。使用 service 和 deployment 资源对象,Peer 和 orderer 节点等都是有状态服务,账本数据挂载到磁盘上,保证 peer 节点重启后数据不会丢失。
为使外部可以访问 K8s 集群中的节点,从而对区块链网络进行操作和调用,需要进行节点的端口映射,在宿主机上分配物理端口。但这样带来的问题是,因为物理端口资源有限,需要建立合理的端口分配规则,并对端口进行全局管理,防止在分配和节点迁移过程中出现端口冲突。
而通过对区块链网络建立 API 网关,外部通过 API 网关来和区块链网络进行交互,操作区块链网络。因为 API 网关节点运行在 K8s 集群中,所以只需要暴露 API 网关的端口,区块链网络中的节点端口不再需要暴露,从而解决了端口冲突的问题。
ClientAPI设计
简易性
Client API 的调用依赖很多参数,通过将大部分参数写到配置文件中,简化了客户端的调用。比如下面的代码,客户端只需初始化配置文件,在调用的时候指定要调用的链码方法 transfer 和参数 args:
配置文件 blockchain_client.yaml:
高性能
优化 Fabric SDK,将同步 API 封装成异步 API;另外客户端的调用并不需要每次都访问区块链网络中的所有节点,通过对需要访问的组织参数化,并轮询访问组织中的节点。比如一个区块链网络有两个组织,每个组织 3 个节点,从一次调用要访问 6 个节点,现在默认只访问 1 个节点,客户端的性能得到大幅的提升。
高鲁棒性
Fabric 1.1 SDK 没有提供获取 channel 中所有正常运行节点的能力,当 channel 中新加入节点或者节点宕机,客户端无法感知到区块链网络拓扑的变化。所以,客户端需要监听服务端拓扑信息的变化,并对访问异常的节点进行主动剔除。而在 Fabric 1.2 中,增加了 Service Discovery,可以动态的发现区块链网络中存在的 Orderer 节点,Peer 节点,已安装的 chaincode 和背书策略等,简化了客户端逻辑。
我们知道 fabric 的交易处理流程中,背书节点模拟执行交易并进行背书,记账节点保存区块到账本。记账节点在接收到区块后,会先检查区块里包含交易的有效性。高并发场景下,在一个区块中对同一个 Key 多次操作可能会导致 MVCC 校验失败,被标记为无效交易。解决方案之一是失败后进行重试。
另外,当链码调用服务端成功,返回客户端超时。因为客户端每次调用都会在客户端生成一个 txID,所以在发生超时时,可以先根据 txID 查询交易状态,如果交易 txID 不存在,再发起重试。
创新性设计
K8s 管理链码容器
当前区块链网络中的背书节点 peer 和排序节点 orderer 都用 k8s 管理起来了,而链码容器的创建和启动是通过 Peer 节点调用 docker API 进行管理的,链码容器在 k8s 的管理之外。
分析链码容器的创建流程:在链码实例化或者链码镜像、容器不存在时,Peer 节点会调用 Docker API 创建链码镜像,并启动链码容器,注册链码 handler 到 Peer 节点。
在链码镜像创建的过程中,使用了 Docker 的多阶段构建(multi-stage build)特性,这也是 Fabric 官方文档中要求 Docker 的版本要在 17.06.2-ce 以上的原因,因为在这个版本中才添加入的多阶段构建特性。
多阶段构建通过构建过渡镜像并产生输出,并作为下一个镜像的输入,组成 Pipeline,最后输出到下游基于 docker build 构建的最小镜像中。这样就能在一个过渡镜像中编译代码,在最终的镜像中只使用它的输出。例如,Java 开发者通常使用 Apache Maven 来构建应用,但是运行应用却不需要 Maven。
链码容器镜像的构建分为两个阶段:第一阶段是基于 go 语言的链码基础镜像 ccenv,启动一个临时容器,通过 go bulid 来编译链码,输出链码的可执行文件;第二阶段将链码的可执行文件作为输入,构建链码镜像。
ccenv 作为 go 语言的链码基础镜像,其中安装了 chaintool、go 语言的链码 shim 层。在链码容器生成过程中作为编译环境将链码编译为二进制文件,供链码容器使用。通过多阶段构建大幅度的减小了链码镜像的体积,方便保持链码容器自身的轻量化。
Fabric 对链码的管理提供了抽象的接口 VM interface:
当前有两种实现:DockerVM 和 InprocVM。通过添加 K8sVM 实现 VM 接口,由 k8s 的 api 来启动链码容器,并对其进行管理。
链码调试
正常情况下,链码运行在容器中,将链码部署到区块链网络中,需要经历如下步骤:
如果在链码的开发和调试阶段,这个流程太过复杂,并创建了大量无用的链码镜像和容器。用户无法专注于链码本身的开发和调试
其实,Fabric 支持开发模式启动节点,在这种模式下,能够使用 IDE 直接运行和 debug 链码。
在开发模式下,链码直接以可执行程序运行,开发调试不再需要创建链码镜像。
在此基础上,BaaS 提供了链码的可视化在线编辑器,屏蔽底层细节,用户可以专注于链码本身,进行快速的开发和调试,减轻了用户的接入和开发成本。
在安全性上,将调试链码运行在隔离的 docker 环境中,和宿主机进行资源隔离。
多维立体监控
为了做到对区块链网络的全方位监控,我们基于 Prometheus+Grafana 实现了多维立体监控。
其中,Prometheus 负责采集数据和推送告警,Grafana 查询 Prometheus 收集到的数据展现可视化界面。Exporters 会基于多维度采集部署在 kubernetes 中的所有节点的数据,包括 Peer、Orderer、Ca 节点,然后 Prometheus server 会定时拉取 Exporters 收集到的度量。
通过在 Prometheus 添加了一系列的告警规则,当规则被触发时,Prometheus 通知 Alertmanager,Alertmanager 会对告警进行分组和抑制,避免因同一异常导致出现大量告警,最后通过告警服务来发送通知到用户。
总结
本文主要介绍了58 BaaS 中基于 Hyperleger Fabric 从 0 到 1 的演进过程,主要包括区块链底层网络的搭建过程,Client API 的设计 与实现,如何通过 k8s 对链码容器进行统一的管理,链码调试功能的实现和监控系统设计 与实现等。
同时 58BaaS 也支持基于 Ethereum 的区块链网络的搭建。当前 58BaaS 仍在快速的演进中,后续我们会在功能的完善性、系统的稳定性、平台的支撑性等方便不断的优化,欢迎对区块链感兴趣的同学和我们一起交流。
kubernetes api servers showing down in prometheus (kube-state-metrics) –“forbidden: User \”system:anonymous\“ cannot get path \”/metrics\“”, 【区块链笔记整理】区块链中的oracle预言机