首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Fabric系统架构设计

公众号回复“1”,拉你进区块链技术讨论微信群

作者:冯翔

来源:区块链兄弟

本文约9700字+,阅读(观看)需要55分钟

本文节选自《区块链开发实战:Hyperledger Fabric关键技术与案例分析》

区块链的概念比较新,但是区块链的技术都是已经存在的技术。新概念和现有技术结合之后会产生一些新的特性,这些特性决定了采用区块链技术的系统架构和现有的系统架构之间既有联系又有区别。基于区块链技术的系统在进行技术架构设计的时候除了需要考虑到现有技术架构的特点之外,还需要考虑到区块链技术的自身特点。

Fabric作为一个典型的区块链技术框架,其系统架构设计也需要遵循上述特点。 本章内容将介绍如何对基于Fabric技术系统进行系统架构设计。

9.1 Fabric架构中组织的规划

组织是Fabric中非常重要的概念,所有的peer节点、用户账号都必须属于一个组织。Fabric中的组织在现实世界中可以是一个公司,一个企业,或者一个协会。在Fabric中,组织通常是具有承担数据信用责任的区块链系统参与方。在设计一个Fabric系统的时候,第一步要做的事情就是收集系统的参与者,然后从这些参与者中选出相关的组织。组织被选出之后需要确认组织的管理方式,组织的管理方式是指组织在遇到问题的时候协作的方式,这些工作跟多的是线下的协调工作,但是经过协调之后组织之间必须达成共识确认一种组织管理方式。

综上所述我们认为在Fabric架构中的组织规划工作实际上需要完成两件事情:确认组织和制定组织之间的管理方式。

9.1.1 确认组织

目前在设计Fabric系统的时候,如何确认系统的参与者是否可以成为一个组织还没有统一的标准。根据我们在Fabric项目中的实施经验,我们给出以下条件供读者参考。我们认为一个参与者如果想要成为Fabric系统中的组织,必须具备以下条件:

是否对区块链中的数据具有有效性检查的权力

是否具有独立发展下属成员的权力和资格

是否是系统核心业务的不可或缺者

具有以上条件的系统参与者都可以成为系统的组织。参与者成为组织之后,会有自己的组织编号、域名、证书等信息。成为Fabric系统组织的参与者将有机会参与到Channle的维护工作,同时成为Fabric系统的组织之后,相关的参与者将会拥有自己的认证服务器,通过这些认证服务器可以随意添加组织内部节点。由此可见在系统参与这中确认组织是Fabric系统架构设计的重要组成部分。

9.1.2 组织的管理方式

在组织确认之后,接下来的问题是要确认系统对组织的管理方式,所有管理方式中最重要的是新组织的加入问题。在系统运行的过程中组织不是一层不变的,由于业务的变化会有新的组织加入到系统中或者将已有的组织从系统中删除,针对这些操作需要制定相关的规则。在Fabric系统的架构中协调组织的管理方式也是系统架构设计的一部分。

我们知道Fabric是个联盟链,联盟链的特点是不是所有的组织都可以随意加入到区块链中。如果想要加入到区块链中,需要一定的准入机制。在Fabric系统中,如果新的组织想要加入区块链中,需要所有组织的一致同意才可以加入。如果区块链的现有组织中有任何一个组织不同意新组织的加入,那么新组织就不能加入到区块链中。如果需要将现有的组织中的一个删除,也需要所有的组织的签名。

在实际的操作中,对组织的管理实际上就是对组织所拥有的证书的管理。在前面的内容中我们介绍了Fabric系统架构设计的第一步是确认组织,组织确认完成之后会生成组织所需要的相关的证书,证书是组织在整个区块链中的身份标识。举个这例子,如果系统中的所有组织都允许新组织的加入,那么需要所有组织用其特有的证书对相关的操作进行签名后才能正确完成这些操作。通常对Fabric的组织证书的管理的方式可以采用以下两种模式:集中式管理和联盟式管理。

1.联盟式管理

联盟式管理是Facric设计的初衷,如果对组织的证书采用联盟式管理的方式,那么系统初始化完成之后需要将生成的各个组织的相关证书(包括 组织的证书,组织的用户的证书,组织中所有节点的证书)全部提供给相关组织(或者这些证书由相关的组织自行生成),以后这些证书由所属组织独立维护。组织的证书采用联盟是管理的好处是所有参与的组织之间是对等的,可以共同参与整个联盟链的管理。

但是坏处也是明显的,整个联盟链中没有一个统一的管理机构,如果有组织之间发生冲突,那么只能通过协商的方式处理,整个系统没有仲裁结构。举个例子,如果需要删除区块链中的某个组织,必须获取包括被删除组织在内的所有组织的同意才能完成删除操作。这个时候如果被删除组织不同意,那么无法完成删除操作。由此可见采用联盟式管理方式必须建立再组织之间互相熟悉的基础上面。

2.集权式管理

正是由于联盟式管理出现了管理不统一的问题,所以才存在这另外一种管理方式及集权式管理。在集权式管理中,整个区块链中存在一个中心组织,该中心组织统一管理区块链中的所有组织。区块链中所组织的管理员账号的证书讲被收回,由中心组织统一管理。如果需要增加新的组织或者删除已经存在的组织,只有中心组织同意即可完成相关的操作。

联盟式管理和集权是管理那个更好呢?当然是联盟式管理更好,因为联盟式管理更加符合区块链的哲学。但是我们在具体项目中需要考虑到历史遗留的问题,具体选择哪种方式需要根据项目的具体情况来决定。

9.2 Fabric系统的结构

在确定了区块链中的组织和组织之间的管理方式之后,接下来要做的事情是设计Fabric的系统结构。在本书前面的章中我们知道,在一个完整的Fabric系统中有Peer,Orderer,Fabric-ca,kafka等模块组成。其中Peer,Orderer是Fabric的核心模块,Fabric-ca-server为Fabric的扩展模块,负责动态生成Fabric的账号。而Kafka是一个独立的消息队列,负责存储Fabric的打包数据。这些系统的关系如图9-1所示。

图9-1 Fabric系统结构图

通过图9-1我们可以发现,Fabric系统是通过组织来划分的,每个组织内都包含承担不同功能的peer节点,同时每个组织都有自己对的fabric-ca服务器。所有的组织公用一个统一的Orderer集群。因此在设计Fabric系统结构的时候需要对每个模块的内部属性和模块之间的联系方式进行一定的规划。具体可以通过逻辑层和物理层两个方面考虑

9.2.1 Fabric系统的逻辑结构

逻辑结构主要是描述Fabric系统中组织与组织以及组织内的关系。逻辑结构是整个系统业务模式的直观反映,通过逻辑结构可以大致了解系统的范围,为后面的设计打下基础。在设计Fabric系统逻辑结构的时候,可以参考图9-1中的Fabric系统架构图,通过绘制该系统架构图,可以了解整个系统的逻辑结构,确定系统设计的范围。在设计Fabric系统的逻辑结构的时候,我们建议读者以图9-1为例,绘制出整个系统的架构图,并以此作为后续设计工作的基础。

在系统的逻辑结构被确认之后,在Fabric系统的逻辑结构设计过程中还需要确认各个组织所使用的域名。在Fabric的初始化配置中很多地方需要使用到相关的域名,域名是Fabric系统中是很多模块(比如Peer,Orderer等)的访问路径,因此需要在逻辑设计阶段确认相关的域名。我们建议以表9.1为例,来制作组织域名匹配表。

表9.1 Fabric系统组织和域名匹配表

上述表格建立之后,需要经过区块链中所有组织的集体确认后方可使用。

注意:上述域名最好是经过备案后使用。

9.2.2 Fabric系统的物理结构

在设计Fabric系统的物理结构的时候需要注意配置文件的路径和访问域名。因为这些配置文件的路径有些是会被写到系统的创始块中的,一旦写入到创始块之后,当系统的在其他服务器上面部署的时候必须保证配置文件的路径和创始块中的路径是一致的,否则系统会出现错误。

同样,对于域名配置也是这样的,一些域名一旦被配置之后相应的域名信息会被写入到创始块中,后面修改非常困难。因此在系统正式发布时的时候需要使用正规的域名(如果是在国内,使用的域名必须是经过备案的)。

目前Fabric系统中会写入到创始块中的配置信息是configtxgen模块的配置文件,我们截取部分配置代码如下所示

- &Org1 # DefaultOrg defines the organization which is used in the sampleconfig # of the fabric.git development environment Name: Org1MSP # ID to load the MSP definition as ID: Org1MSP MSPDir: /opt/hyperledger/fabricconfig/crypto-config/peerOrganizations/org1.robertfabrictest.com/msp AnchorPeers: # AnchorPeers defines the location of peers which can be used # for cross org gossip communication. Note, this value is only # encoded in the genesis block in the Application section context - Host: peer0.org1.robertfabrictest.com Port: 7051

在上述配置示例中,MSPDir属性和AnchorPeers属性的是都会被写入到创始块中。

9.3 Fabric中Channle的设计

Fabric的数据存储结构被设计成多账本体系,每个一个账本在Fabric中被称为Channel,加入Channel中的每个peer节点都是对等的,也就是说同一Channel中的所有peer节点都保存一份相同的数据。但是Fabric目前并没有提供分布式存储的解决方案,这导致了在加入同一Channel的peer节点服务器中都会重复的存储相同的数据。这种存储结构在数据量非常大的时候会影响peer节点读取数据的性能。

基于Fabric这样的存储特性,在设计Fabric系统中的时候需要对Channle存储方式进行相关的设计。Fabric中对Channle的存储方式进行设计的内容主要是:首先对Channle的大小进行评估,如果单个Channle的数据量或者数据的存储空间都非常大,那么可以将一个非常大的Channle拆分成本若干个相对比较小的Channle。

我们通过一个例子来说明如何拆分Channle。假设在Fabric系统中我们有这样一个Channle,该Channel中包含的数据可能超过10亿条,数据文件的大小可能超过500G。如果按照Fabric现有的设计方式,Channle和节点的分布如图9-2所示:

图9-2 Fabirc大Channle分布示意图

根据图9-2所示,所以后的Peer节点都要存在大约500G的数据,这显然对单个Peer节点造成了比较大的压力。这个时候我们可以采取对Channle进行分割,我们将每个Channle的数据限制在2000万条,经过分割之后的Channle结构如图9-3所示:

(图9-3)Fabirc大Channle分布示意图

通过图9-3我可以看到经过分割处理之后的Channle体积缩小到原来的三分之一的。对Channle进行分割处理还有一个好处就是,如果数据继续增长只需要增加一个新的Channle即可,这样李理论上可以应对数据的无限增长。

9.4 chaincode

在本书的第7章中我们详细的介绍了Chaincode原理、开发和使用等基本功能和操作,这里不再复述。通过第7章的介绍我们知道Chaincode是Fabric重要的组成部分,对Channle进行的任何操作都是通过Chaincode进行的。在设计Fabric系统的时候针对Chaincode的特性需要关注一下几个问题。

(1)Chaincode只作为数据的加工者存在,不要存储中间状态。

同一份Chaincode通常会部署在多个Peer节点中。因此每个机器的状态可能是不一样的,因此Chaincode的代码中,尽量不要通过本机的属性(时间错,硬盘编号)生成诸如随机数等包含节点特定属性相关的数据。把Chaincode当成一个数据处理状态机,只进行数据的校验、读取、存储等基本操作。

(2)在Chaincode中避免进行CUP和内存密集型运算。

Chaincode是运行在容器中的,每个Chaincode分配的资源是有限制,因此如果在Chaincode中进行大cpu或者大内存的运算可能导致容器的崩溃。在设计Chaincode代码的时候需要考虑到这一特点,我们建议在将Chaincode部署到生产系统之前首先进行相关的压力测试,以便获取当前Chaincode在运行过程中cpu和内存等相关系统参数的阈值以便对chaincode代码进行优化。

9.5 数据访问层

在Fabric中当需要对系统进行管理操作或者调用Chaincode的时候通常可以通过两种方法:CLI命令行工具和Fabric SDK调用。CLI命令行工具需要获取peer节点所在主机的操作系统的账号登录操作系统之后使用,这种方式通常被系统管理员采用。如果需要在业务系统中通过代码的方式同Fabric进行交互,只能通过Fabric的提供的相关语言的SDK编写相应的代码和Fabric进行交换。在设计这些访问代码的时候通常会采取两种方式:嵌入式和中间件式。这两种代码的设计方式如图9-4所示:

图9-4 业务系统访问Fabric代码设计示意图

在图9-4所示的两种方法中,我们建议采用第二种方式。在Fabric系统中设计一个独立的中间层封装对Fabric常用操作,将这些操作采用通用接口的方式提供给业务系统调用。我们认为这中设计方式有以下好处:

1.解决Fabric记录状态返回不实时的问题

Fabric是基于区块链的分布式总账系统,所有的数据存在在区块链中。区块链的区块生成是需要时间的,目前Fabric的Orderer模块专门负责将交易打包成区块。区块的生成按照时间或者交易的数量进行打包,比如可以设置每一分钟打包一个区块或者每个1000条记录打包一个区块。不伦采用哪种方式区块链的生成都是需要一定的时间。

因此Fabric系统中是无法立即响应数据操的作状态,如果提交一笔交易之后需要一定时候之后才能获取该交易的操作结果。如果采用将Fabric相关的操作集成在一个中间件中,遇到类似的场景的时候可以在数据处理完成之后,通过中间件将处理结果推送给业务系统进行后续处理。这样可以在有效解决业务系统的等待问题同时还可以降低业务系统的开发难度。

2.有利于系统进行负载均衡

Fabric并不是一个可以承载大并发读写的数据系统,当系统请求的并发比较多的时候Fabric会产生阻塞,遇到这种情况通常可以采用增加peer节点的方式来减轻单个节点的负载。

举个例子,在Fabric系统中某个Channel1中存在一个数据访问节点peer1,该节点专门负责接受外部系统的访问请求。随着系统运行外部系统的请求数量会逐步增加,这个时候peer1节点可能无法满足需求因此需要增加一个新的节点分担peer1节点的负载,我们将新增加的节点成为peer2。增加的peer2节点加入Channel1之后,系统会自动将Channel1中的数据部署到peer2中。

然后在peer2中部署和peer1中同样的Chaincode,这样peer2就可以提供和peer1一样的功能。通过这样的方式Fabric系统能够简单的对系统进行横向扩展。但是这种特性对业务系统访问Fabric的方式提出了相关的要求。假设在业务系统编写访问Fabric的代码,这个时候如果Fabric增加了一个新的访问节之后,业务系统可能需要进行重新启动、打包等维护工作。这样可以能会降低业务系统的稳定性。如果将对Fabric的操作封装在一个独立的中间件中,可以在不影响业务系统的情况下直更新中间件系统即可完成相关的升级工作。

除此之外,通过独立的中间件系统访问Fabric还有一个好处就是,可以在中间件中集成相关的负载均衡算法,根据相关peer节点的性能来决定接受的请求数量。

3.隔离客户端系统采用的开发语言

Fabric提供了基于Grpc的接口描述文件,理论上任何语言只要能够支持Grpc协议都能够很好的和Fabric进行通信。但是从头开始实现Fabric的Grpc协议工作量非常大,而且要进行很多测试工作。目前Hyperledger项目已经实现了Nodejs、Go、Java、Python这个四个语言的SDK,应用这四种语言开发的系统可以非常容易的和Fabric进行通信。但是常用的编程语言有远不止这么多,开发业务的系统的编程也不会局限于这四种语言。

比如,业务系统采用的开发语言是PHP,这就需要从头开始用php根据Fabric提供的GRPC的描述文件生成相关的代码,这个过程比较繁琐而且容易出错。这个时候如果采用Nodejs、Go、Java、Python这四种语言的一种开发一个通用的中间件,然后通过一些常用的协议(比如JSON-RPC)暴露接口,这样能够屏蔽由于业务系统的编程语言多样性带来的问题。

9.6 历史遗留系统的兼容

在采用Fabric架构的系统中我们常常面对这样的场景:需要将现有的系统和Fabric系统对接。比较常见的是溯源系统,这样的系统在引入区块链技术之前业务方已经有一个基于传统技术架构的系统,该系统已经运行了一段时间并积累的大量的数据,现在为了提高数据价值准备将所有的历史溯源数据存放到到区块链中,并且在系统改造完成之后,新产生的溯源数据也需要存放到区块链中。在实际工作中这样的业务场景和需求是经常会遇见到的。

在上述溯源的业务场景中,最核心的问题是历史遗留系统和Fabric的结合。针对这样的业务需求,我们建议从账号同步和数据融合这两个方面来进行考虑。

1.业务系统的历史账号和Fabric账号的同步

如果业务系统中存在历史遗留系统,首先需要仔细分析历史遗留系统中的账号体系。在分析史遗留系统中的账号体系的时候可以从账号是否会继续增加和现有账号的数量这两个维度来考虑历史遗留系统的账号体系和Fabric账号体系的融合。

(1)历史遗留系统中的账号体系中账号是固定不变

在这种情况下如果账号的数量比较少可以通过Fabric的cryptogen模块生成相应数量的账号信息,然后将生成的账号文件和历史遗留系统的账号进行绑定。如果账号的数量比较多,那么可以借助Fabric-ca-servder来对这些账号进行管理,通过Fabric-ca-server提供的RESTAPI接口可以将历史遗留系统的账号导入到Fabric-ca-server中。在调用Fabric-ca-server提供的RESTAPI导入数据的,每次调用成功之后都会返回当前创建账号的证书等信息,通过这些信息可以完成和历史遗留系统账号体系的绑定。

(2)历史遗留系统的账号会持续增加

如果是这种情况,那么只能采取Fabric-ca-server来管理账号,首先通过Fabric-ca-server提供的RESTAPI接口可以将历史遗留系统的现有账号导入到Fabric-ca-server中帮完成绑定。对于新增增加的账号,每次创建账号之后,调用Fabric-ca-server的接口生成新的账号并完成绑定。

说明:关于Fabric的账号以及Fabric-ca-server的相关内容请参考本书的第六章。

2.业务系统历史遗留数据和Fabric的融合

关于历史遗留系统的已有数据保存区块链中的问题是一个比较麻烦的问题。在处理这里的问题的时候候会有一个矛盾。由于历史遗留数据是发生在以前的,但是区块链中每条交易都会在系统级别记录一条数据的时间戳。这个时间是客户端无法修改的并将永远保存。这个时候如果进行数据数据初始化就会发生数据存储时间不一致的问题,及历史数据的系统时间戳和业务时间戳是不一致。这可能会导致数据有效性受到质疑。这个时候区块链技术已经无法解决这个问题了,只有联盟链的所有参与方统一达成共识,统一接受这样的事实。针对这种问题我们推荐两种解决方案供大家参考,这两种方案分别是:时间戳截取法和channel截取法。

(1)时间戳截取法

时间戳截取法是通过设定某个特定的时间点,在该时间点之前的数据为历史数据,时间点之后数据为新数据。当系统中需要用数据的时间戳的时候,对于时间节点之前的数据以存在交易记录中的历史时间为准,对于时间点之后的数据一系统时间戳为准。

(2)channel截取法

在使用channel截取法的时候,将历史数据存储在特定的通道中。当需要使用历史数据的时候从特定的通道中获取相关的数据,如果需要使用新生成的数据从新创建的的Channel中获取数据。

上述两种方法都需要在历史数据保存到区块链中的时候将历史数据中的时间戳一并保存到区块链中。

注意:在设计区块链系统的时候,技术不是万能,很多时候需要所有的参与达成共识才能有效的解决问题。人的因素是设计区块链系统必须充分考虑的一个因数。区块链提出了一个区中心化的理想中的模型,直接用来改造现实社会是有问题的。在设计基于区块链技术的系统的时候需要在理想和现实之间达成妥协。

9.7 Fabric系统的维护和管理

区块链系统和传统的以数据库为核心的系统有很多不一样的地方,因此在对系统进行维护的时候需要着重主要以下三个问题:

1.数据备份

我们知道Fabric系统是一个区块链系统,而区块链本身具有分布式数据库的特性,整个系统强调最终一致性,在某个时间点很难确认那个节点的数据是最完整的,所以传统数据库系统中采用的导出导入的备份和恢复方式不适合Fabric系统。但是可以利用区块链系统分布式数据库的特性,通过增加节点的方式进行备份。比如在Fabric系统中设置专门的数据备份Peer节点,该节点在加入相关的Channel之后不接受任何外部程序的访问请求,专门作为备份节点使用。

2.系统升级

Fabric的一个开源系统,目前处于快速发展阶段,代码的变化比较频繁。在现阶段采用Fabric系统开发系统,一定要注意系统升级之后数据格式的兼容性。比如Fabric0.6版本和Fabric1.0版本的数据是不兼容的。我们建议在开发基于Fabric系统的时候一定要做好相关的操作日志,如果出现升级之后数据格式和系统版本不兼容的情况可以在联盟所有参与方共同协商并且都认可的情况下进行相关的数据恢复操作。

3.Orderer节点的多机备份

Orderer模块是Fabric系统中的核心模块,Orderer模块主要负责数据的排序和打包,一旦Orderer节点出现问题,整个区块链系统都会出现问题。因此Orderer节点应该避免单个节点。可以部署几个拥有相同创始块的Orderer节点,然后把这些节点指向同一个Kafka集群。

9.8 本章小结

Fabric作为区块链技术框架有其自生的特点,在开发基于Fabric技术框架的系统中的时候不能在不经考虑的情况下随意使用,基于Fabric技术框架的系统也是需要设计的,本章主要介绍Fabric系统在设计是需要注意的事项。良好的架构设计是系统成功的一半,区块链系统也是需要进行架构设计。

文章发布只为分享区块链技术内容,版权归原作者所有,观点仅代表作者本人,绝不代表区块链兄弟赞同其观点或证实其描述。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180620B1LT1300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券