2018 年 9 月

33 卷,第 9

此文章由机器翻译

微服务-作为微服务的架构师区块链应用程序

通过Stefano Tempesta |2018 年 9 月

微服务和区块链的智能协定有很多共同点。同时在认为它们不在隔离 (链上) 中运行并与外部通信 (链) 通过基于消息的通道。它们应很小的大小,为运行自主、 独立地开发和更好地执行时分散式网络上部署它们。

本文介绍设计原则、 项目和用于生成区块链应用程序的代码示例使用微服务体系结构样式并将它们部署在 Microsoft Azure 区块链的平台上。

微服务完全体现 Unix 原理的精神:做一件事,执行该操作也 (tcrn.ch/2vnq5Pb)。微服务是支持基于消息的通信通过互操作性的界定作用域的一个独立的可部署组件。给定此内部部署,微服务体系结构是工程的一种帮助生成的单功能微服务组成的高度自动化的可发展软件系统的样式。

区块链应用程序之间的相似微服务和哪些设计原则可以从微服务体系结构应用于分散式世界有什么?中的表图 1将微服务和智能协定根据特定的设计属性进行比较。

图 1 微服务和区块链设计原则

设计原则 微服务 智能协定
单一责任 通常会在单个实体提供一个 CRUD 接口。 螃蟹方法 (稍后在本文中使用) 在单个对象上定义角色、 状态和验证工作流的相关逻辑。
界定的上下文 不依赖于其他服务拥有它对于永久性存储的数据模型。 其他智能协定上没有依赖项,以及作为首选的数据模型利用链上数据模型 (即,区块链本身)。
消息已启用 可以利用进行服务间通信的 API 网关和内部服务通信的服务总线。 可利用"oracle"或"cryptlets"进行的链外数据访问或公开一个 REST API 等 Azure Blockchain Workbench 工具。
自主开发 多种编程语言和框架。 存在多个区块链平台可用,尽管当前没有跨平台通信。
独立部署 恰当合理的设计 (事件溯源,CQRS) 可以减少或完全删除依赖项。 相似的设计模式将应用 (在本文中所述)。
分布式和分散 分布式体系结构,而不是集中式"单体结构。" 内置分布式和分散数字账本的设计。

 

设计微服务的形式的区块链应用程序到你的解决方案可带来以下优势:

  • 允许许多软件工程计划要并行运行。
  • 降低软件开发和测试团队之间的依赖关系。
  • 支持多个技术、 语言和框架。
  • 将提升可释放代码通过创新的易用的性。

微服务通常说出与外界通过与客户端共享同一种语言,例如 JSON 或 SOAP,应用程序编程接口 (API) — 跨不同的技术 (.NET、 Java、 提供支持消息传送的系统的通用语言Node.js 等) 和平台 (Windows、 Linux)。正如您将看到更高版本在本文中,这是规则同样适用于区块链由 Azure Blockchain Workbench,公开的 API。

从分散的应用程序到微服务

如果您熟悉的将你的服务器不宠物牛等 DevOps 观点 (bit.ly/2vrdM4p),可能会将相同的方法应用到你的源代码。可轻松地释放代码可以降低技术债务,将提升工程过程的现代化,减少运营成本,方法是优化基础结构 (例如,在容器或完全无服务器的配置)。

设计微服务体系结构原则的区块链应用程序还可以带来业务优势。软件系统中的提高的效率可降低基础结构成本和容量相关的服务中断的风险。这些方面的特定值与专用区块链的是其中的成本效益和服务持续性是为企业的关键要求。

微服务体系结构主体可以支持使用可更换的元件,减少可能会导致老化不可靠的环境中的技术债务。密度,以太坊中的智能协定的编程语言都有一种机制,用于指定在其执行的每个协定的确切运行时版本。随着时间推移,智能协定的版本编号可以用于标识已过时的区块链存储代码可能替换的候选项。已处理只是请记住,在区块链,智能协定的 (即,将"挖掘"块的一部分) 不能删除 — 协定的新版本必须发布为将来的交易。

另一个优势是更好地运行时可伸缩性,使软件系统可以扩大或收缩的需求。智能协定实现微服务可在专用业务或联盟环境要分发的事务工作负荷中的请求权限区块链和挖掘节点以更灵活的方式。

在其最基本的级别,微服务体系结构是有关分解应用程序或系统为较小部分和获取受益于分布式安装程序。同样,在区块链运行的智能协定受益于对等网络的分布式特性。微服务体系结构面向设计,通过智能协定可以提供更高的效率、 可伸缩性和可管理性 — 非常重要的企业中的区块链解决方案正常实现的所有属性。

 

分散式的域驱动设计

编写用于分散式区块链数字账本的应用程序和正在使用典型的分布式系统中,例如存储隔离、 异步消息传送和分布式的事务的基础结构和软件要求。区块链应用程序还需要身份验证的用户和设备和权限,无法执行智能协定中的特定操作。我展开上常用的域驱动设计 (DDD) 方法,请参阅"分散领域驱动设计 》 或 DDDD 考虑实体、 进程和区块链系统属性的做法。

让我们开始定义的域或的智能协定内数字账本的执行上下文。智能协定表示作为工作流,区块链应用程序的业务逻辑,由消息发件人 (用户或设备执行约定的函数) 和状态 (的参数表示的约定标识工作流的每个阶段作为一条消息发送到一个函数,并且其内部状态)。第三方 (同样,用户或设备) 可能会受到智能协定的函数的执行。

在此上下文中,我们引用作为应用程序角色所涉及的所有参与方。创建约定的第一个应用程序角色称为发起方。在协定的内部状态的更改,可能会引发一个事件以指示此更改的智能协定后,其他部件或外部应用程序。这适用的典型模式,例如,填充用于处理由智能协定和发布消息到相关侦听器引发的事件使用服务总线的链外数据。图 2标识智能协定中的工作流中所涉及的实体。

智能协定中的工作流实体
图 2 智能协定中的工作流实体

以太坊使用 Solidity 作为编程语言编写的智能协定自强制实施业务逻辑。在 Solidity 智能协定是类似于面向对象语言中的类。每个协定包含角色、 状态和函数,实现执行组件、 阶段和业务流程的操作。

中的代码段图 3显示不同类型的变量声明中 Solidity 角色、 状态和可能用于打赌的应用程序智能协定中的属性。角色 (gambler 和 bookmaker) 被定义为地址,这是用户或以太坊中的协定的唯一标识符。状态是一个枚举标签标识放置通过智能协定匹配的当前状态。函数,您将看到更高版本,定义了状态更改。匹配量表示为无符号的数字 (目前,Solidity 不支持十进制值)。

图 3 的角色、 状态和打赌智能协定中的属性的声明

pragma solidity ^0.4.20;
contract Betting
{
  // Roles
  address public Gambler;
  address public Bookmaker;
  // State
  enum BetType { Placed, Won, Lost }
  BetType public State;
  // Properties
  uint public BetAmount;

请注意,我以目标为此智能协定的密度最新版的指示。它是指示此杂注指令以避免与将来的密度的编程语言和编译器版本不兼容问题的好办法。这也有助于确定可能需要使用新版本以支持更新的代码替换智能协定中的旧代码。从区块链中删除现有智能协定的过程被称为"自毁。"

智能协定应具有单一责任和包含尽可能少的业务逻辑 — 以最佳方式仅验证所需逻辑可靠性协定是否有效。在我打赌的应用程序,智能协定可能会公开用于通过 gambler 下注和确认 win 或通过 bookmaker 丢失函数。货币可能的匹配工作流一部分的两个角色之间进行交换。需要验证的协定的货币交易的通常模式会看到量传输发生在两个阶段中,如下所示图 4。Gambler (发起方的协定) 将成为匹配放置到特定数量,然后存储在智能协定。如果此匹配结束-赢得,获胜的量,由 bookmaker,指示被传输到 gambler。否则,bookmaker cashes 匹配量。

把赌注压工作流
图 4 把赌注压工作流

如中所示图 5,Solidity 中此智能协定的实现需要多个函数,如下所示定义为工作流,每个操作:

  • 构造函数将消息发送方存储为 gambler;这是启动智能协定的角色。
  • 匹配函数接受作为输入的金额,将执行一些验证 (可调用此函数只能由 gambler 和量应为大于零),然后将匹配量传输给协定。若要允许的链上货币传输,务必标志将函数作为应付账款。
  • 赢得函数,验证调用程序不 gambler 之后, 将获胜的量传输到 gambler 并关闭此匹配,如"结束-赢得"。
  • 丢失的函数,这将再次可以只能由调用 bookmaker,传输量最初打赌,和现在丢失到 bookmaker gambler,并关闭此匹配作为"丢失"。
  • 通过关闭一赌博,删除 gambler (其地址设置为 0x0) 和量设置为零,让另一个匹配。

图 5 打赌智能协定中的函数

constructor() public {
  Gambler = msg.sender;
}
function Bet(uint amount) public payable {
  require(msg.sender == Gambler, "Only a gambler can place a bet.");
  require(amount > 0, "Amount should be greater than zero.");
  BetAmount = amount;
  address(this).transfer(amount);
  State = BetType.Placed;
}
function Won(uint amount) public payable {
  require(msg.sender != Gambler, "Only the bookmaker can mark a bet as won.");
  require(amount > 0, "Amount should be greater than zero.");
  Gambler.transfer(amount);
  Close(BetType.Won);
}
function Lost() public payable {
  require(msg.sender != Gambler, "Only the bookmaker can mark a bet as won.");
  Bookmaker = msg.sender;
  Bookmaker.transfer(BetAmount);
  Close(BetType.Lost);
}
function Close(BetType state) internal {
  Gambler = 0x0;
  BetAmount = 0;
  State = state;
}

尽管简单实现中,这种情况下将标识管理区块链应用程序中的资金支出的典型模式。其他方案可能需要合并 attestable 文件,如文档、 电子表格、 证书和图片。出于多种原因,主要是关于存储限制,不适合于将文件放在区块链。一种常见方法是执行针对文件的加密哈希 (例如,SHA-256) 和共享分布式分类帐该哈希值。外部系统会改为将文件保存到存储机制,例如 Azure 存储或 IPFS (ipfs.io)。

在任何将来的时间执行再次使用相同的哈希算法的哈希将返回相同的结果,除非修改持久化的文件 — 即使只有一个像素修改图像中。此过程将授予证明信息的电子邮件、 文件、 文档、 电话呼叫或视频等对象的时间存在于某个特定点存在。它还会授予的真实性的概念 — 您知道数字资产未发生更改,因为数字账本存储不可变和独立的可验证的所有事务的记录。在企业内容管理的区块链的值的详细信息,请阅读我在发布的文章bit.ly/2OC2Ycp

事件溯源和 CQRS

如前一部分中所述,我建议使用一个功能仅负责生成智能协定。面向功能的设计时的智能协定隔离的重要技术,它不是不足以确保独立支持。智能协定可能会对系统中,尽管在执行过程中被隔离域中的常见数据模型。例如,应用程序中可能有用于管理匹配和另一个用于管理的打赌体育事件的智能协定。把赌注压的智能协定可能引用一个体育赛事,创建两个智能协定 (打赌如果事件不存在,则不能发生) 之间的依赖关系。是否有可帮助避免在智能协定之间共享数据的模型数据的方式?

任何格式和存储 (SQL、 NoSQL、 JSON),我们使用,我们通常模型根据对象和创建、 读取、 更新和删除 (CRUD) 操作的数据库。而不是存储结构,该模型的状态在域中,我们可以存储到我们的世界的当前状态导致的事件。此建模方法称为事件溯源 (bit.ly/2O68nrt)。

事件溯源是有关存储事实。事实是代表事件匹配项的值。如同生活中,我们不能及时返回和更改在过去,我们可以仅在存在来补偿较早的操作中执行操作。数据是固定不变;因此我们始终发出新的命令或事件,以补偿,而不是更新实体的状态。这种方法将在螃蟹的首字母缩写操作-创建、 检索、 附加和 Burn (bit.ly/2MbpUOb),这正是区块链允许执行: 任何数据更新或删除操作,它仅将追加到该链。从区块链中删除某些内容冲突其不可变性,但你可以通过"刻录"收件人地址停止资产传输。

这种方法,一个即时问题是性能。如果任何状态值是事件的函数,可能会假定每个访问的值需要重新计算的源事件的当前状态。显然,这将是速度极慢。在事件溯源,可以通过使用所谓的滚动快照避免此类成本高昂的操作: 在时间中的给定点处的实体状态投影。例如,银行预先计算你的银行帐户余额的每个月的最后一天以便无需求和所有借贷,因为一天的信用额度操作打开你要获取当前余额的银行帐户。

图 6显示打赌的应用程序的结构化数据模型。这有时称为雪花型模型,因为每个实体 (数据库表) 不同于任何其他。

结构化数据模型
图 6 结构化数据模型

事件溯源方法保存单个事实数据时,结构化数据模型将保存仅在系统的当前状态。状态,请在事件溯源,是发生的所有相关事实的函数。不仅这不会向提供完整的可审核性,而且它还使我们可以建立状态投影向任何过去的时间。

若要推送的职责隔离方面进一步,命令查询职责分离 (CQRS) 补充了事件溯源作为数据存储的设计模式。CQRS 可促进有效的单一责任和支持的微服务,并扩展到智能协定。它指出你可以 — 并且应该 — 数据更新分开单独的模型的数据查询功能。

当使用 CQRS,则可以消除了需要跨多个上下文中访问数据。智能协定可以拥有和封装对模型的状态的任何更新并引发此状态更改事件。通过订阅这些事件的通知,一个单独的智能协定可以构建不需要与任何其他协定或外部服务共享的完全独立的查询优化模型。您可以从 Martin Fowler 发布在进一步了解 CQRS bit.ly/2Awoz33

图 7介绍我设计用于使用事件溯源打赌应用程序的数据模型。此简单模型采用相似的结构而不考虑处理的事件。不需要知道匹配要读取的事件序列的当前状态。事件的数据结构取决于事件本身。虽然存在状态的序列中定义工作流中,是从数据模型的角度看不相关。认为更大:在供应链方案中,存在多个工作流和事件,具有不同的实体和属性。结构化数据模型可能会变得复杂,,而基于事件的模型,栏的每个事件,几个不同的属性保持不变。

事件溯源数据模型
图 7 事件溯源数据模型

分布式的事务

共享的数据模型不是唯一的用例,可以将引入智能协定之间的紧密耦合。另一个重要威胁是工作流。不能使用单个原子操作表示大量实际进程。与此类工作流,结果仅是有意义如果可以执行所有步骤。如果序列中的任何步骤失败,相关的系统的结果状态将变为无效。在 RDBMS 世界中,这样的过程被称为"事务"。 数据库事务是在当地通常包含在单个数据库的范围内,并且依赖于之前更新的表上的锁。如果步骤失败,可以回滚之前最终提交已尝试的步骤。

为分布式工作流和无状态微服务,数据锁和原子性、 一致性、 隔离性、 持久性 (ACID) 符合性的传统事务实现 (en.wikipedia.org/wiki/ACID) 是不切实际。Saga (bit.ly/2AzdKNR) 是生存期较长允许运行工作流在松散耦合环境中,而无需进行任何假设复杂系统的每个组件的可靠性的分布式的事务。

Saga,在工作流中的每个步骤执行其部分工作、 注册回调的补偿事务中名为"传送名单"一条消息并将更新后的消息活动链中向下传递。如果下游的任何步骤失败,该步骤查看传送名单,并调用最新步骤的补偿事务,传递回传送名单。在上一步执行相同操作,调用其前身补偿事务,依此类推,直到已执行的所有事务进行都补偿。此模式会导致在分布式事务中的数据的最终一致性 (bit.ly/2v8T360)。由于其高度的容错的分布式性质,saga 非常非常适合于微服务体系结构,以及有关区块链智能协定。

可以在 Solidity 中实现一种通过回退函数传送名单。回退函数是未命名的函数定义为具有任何输入的参数和没有返回值。如果没有任何其他函数匹配给定的函数标识符或每当协定收到经不起考验 (对于以太坊) 时,对协定调用上执行。此外,为了接收经不起考验,回退函数必须标记应付账款。如果不存在任何此类函数,该协定无法通过常规 (地址为地址) 事务接收经不起考验。

值得一提的是,没有应付账款回退函数的协定可以 coinbase 事务,如挖掘程序块奖励的收件人接收经不起考验。协定不能应对这种方式传输和,因此,也不能拒绝它们。这是以太坊,一个设计选择和密度不能解决此问题。约定可具有一个未命名的函数,如下所示:

// Fallback function
function() public payable {
  emit AmountTransfered(msg.sender);
}
event AmountTransfered(address sender);

在以太坊,回退函数是智能协定以允许客户与客户直接传输所必需的。这是因为传输帐户可能需要对这两个外部拥有的帐户 (EOAs) 和其他智能协定进行传输。如 EOAs 只能接受直接传输,以将值传输到另一个帐户的帐户的唯一方法是正在执行的协定,若要实现回退函数。这意味着,想要接受此类转移必须由具有回退的功能准备进行直接传输任何协定。如果没有该函数,则传输会失败,和它就不可能从其他协定接受经不起考验的协定。

最佳做法是在回退函数中没有任何逻辑。可以将代码放入此函数的主体,但最好是避免非常简短的简单日志记录以外的项目。原因是重要且唯一的智能协定:您不希望此函数失败,因为它用完天然气公司。作为经验,你将有足够天然气来引发事件,但不足以将数据写入到存储。

异步消息传送

异步消息传送扮演着关键角色地保管东西松散耦合微服务体系结构中。例如,我们可以使用消息代理来提供事件通知以异步方式,阻止创建每个终结点的可用性和消息格式的依赖关系的点对点连接。智能协定通过相同的令牌,可以从支持消息传送的集成中受益的入站 (从外部更改到区块链内部) 和出站 (从外部应用程序向区块链) 通信。

除了提供 REST API,Azure Blockchain Workbench 提供了基于消息的集成基于会计为中心的事件。事件发布到 Azure 事件网格,并使用者可以将数据引入或基于这些事件采取操作。对于需要可靠的消息传送这些客户端,Azure Blockchain Workbench 将消息传送到 Azure 服务总线终结点,以及。您可以引发事件,例如,以通知用户和系统的事务或智能协定中的状态发生更改。事件通知可以在代码中直接使用或用于逻辑应用等工具 (bit.ly/2n4EgoP) 到的数据的下游系统时触发流。

智能协定通常代表与外部系统和设备集成的业务工作流。因此,事务必须能够包括来自外部系统或设备的数据的分布式账本上启动。您可能想要拥有对源自分布式账本上智能协定的事件做出反应的外部系统。REST API 和消息传递集成提供的功能将从外部系统的事务发送到在 Azure Blockchain Workbench 应用程序,包括智能协定的同时将事件通知发送到外部系统基于发生的更改在应用程序。现在让我们来了解这些类型的集成的端到端解决方案中的每个标识的模式:

  • 向事件使用者的单向事件交付从智能协定。
  • 单向到的事件传递的消息来自外部系统的智能协定。

对事件使用者的智能协定

在第一个方案中,在事件发生智能协定; 中例如,在状态更改或特定类型的事务执行。此事件对下游使用者,事件网格和这些使用者通过广播,然后采取适当措施。此方案中的一个示例是一个事务时,使用者将收到警报和无法执行操作,例如在数据库中记录信息。这是 Azure Blockchain Workbench 遵循以填充其关闭链 SQL 数据库的同一模式。另一个是为特定的状态; 如果转换智能协定例如,当协定将进入"外出时的符合性"状态。在此状态更改情况下,它可能会触发警报向管理员发送。发生这种情况使用过程中所示图 8,其中:

  1. 智能协定转换为新状态,并将事件发送到分类帐。
  2. 分类帐接收,并将事件传送到 Azure Blockchain Workbench。
  3. Azure Blockchain Workbench 从分类帐订阅事件,并接收事件。
  4. Azure Blockchain Workbench 将事件发布到事件网格上的订阅服务器。
  5. 外部系统已订阅到事件网格、 使用的消息,并采取相应的措施。

在对外部系统的智能协定中引发的事件的传播
图 8 传播的到外部系统的智能协定中引发的事件

外部系统到智能协定

此外还有一个方案,从相反方向流动。在这种情况下,传感器生成一个事件或外部系统和从该事件的数据应发送到智能协定。常见示例是数据金融市场,如价格的商品、 股票或证劵传递到智能协定。发生这种情况使用过程中所示图 9,其中:

  1. 为 Azure Blockchain Workbench 创建一条消息将触发与外部系统中发生的事件。
  2. 外部系统具有写入代码以创建此消息中的已知格式,并将其发送到服务总线直接。
  3. Azure Blockchain Workbench 从服务总线订阅事件,并检索该消息。
  4. Azure Blockchain Workbench 启动对分类帐的调用将来自外部系统的数据发送到特定的约定。
  5. 收到的消息,将协定转换为可能的新状态。

通过智能协定到外部系统引发的事件的传播
图 9 传播的外部系统到智能协定所引发的事件

哪种方案中集成的端到端解决方案的实现不在本文的范围。在这两个方向上的集成的很好的示例,请参阅bit.ly/2M8yflL

总之,可以在微服务体系结构和区块链智能协定中找到类似集成模式。两种体系结构的分布式的性质可促进异步消息传送和使用消息代理,事件网格或服务总线的窗体中传达的信息分散到服务和智能协定。设计模式,例如事件溯源,从根本上讲,匹配数字账本和事件驱动方法来关闭链通信不可变的性质。

探索 Azure Blockchain Workbench API

Azure Blockchain Workbench (aka.ms/abcworkbench) 是一种服务,以分钟为单位创建区块链数字账本 (目前,以太坊)。它还提供托管在 Azure 中用于快速开发智能合同,同时最小化担心底层基础结构运行以太坊或类似的区块链平台所需的资源。

如果您是初次接触 Azure Blockchain Workbench,请查看对它的 6 月刊中我介绍MSDN 杂志 》 (msdn.com/magazine/mt846726)。Azure Blockchain Workbench 开发人员提供了一种 REST API 作为网关将桌面、 Web 和移动应用程序到区块链应用程序进行集成。例如,开发人员可以使用 API,使 IoT 设备将数据发送到智能协定。或 API 可供 Power BI 创建区块链数据的可视化效果。API 公开的大量功能的 Azure Blockchain Workbench,如下所示,在操作组中组织图 A,并可用于自动执行以下:

  • 创建和管理的区块链联盟中的工作流。
  • 与联盟、 区块链应用程序或应用程序工作流的用户和组织关联。
  • 区块链上的事务的执行。
  • 检索的事务和区块链中的协定数据。

 

操作组 说明
应用程序 Blockchain Workbench 区块链应用程序的管理。
功能 用户可以执行 Blockchain Workbench 中的功能的列表。
检查器 开发人员工具用来验证 Workbench 配置和区块链智能协定。
连接 连接到区块链网络。
合约 智能协定实例,包括智能协定上采取操作。
图形代理 表示用户的 Azure Active Directory 图形 API 代理方法。
运行状况 区块链 Workbench API 的运行状况状态。
分类帐 支持区块链网络。
用户 Blockchain Workbench 中的用户的管理。

图 A Azure Blockchain Workbench REST API 操作组

对 REST API 的 HTTP 请求均通过 Azure Active Directory (Azure AD) 保护。若要对 REST API 进行身份验证的请求,客户端必须进行身份验证使用有效的凭据,然后才能调用该 API。身份验证是通过 Azure AD 中,各种参与者之间协调和您的客户端提供访问令牌作为证明身份验证。然后,每个 REST API 请求的 HTTP 授权标头中发送令牌。有关如何进行身份验证的客户端应用程序到 Azure Blockchain Workbench REST API 在 GitHub 上查看这些示例**bit.ly/2vxzlAC**。

该 GitHub 存储库包含如何调用不同服务来列出应用程序、 工作流和协定区块链上的其他示例。虽然 Azure Blockchain Workbench 的当前实现支持仅以太坊,未来版本将扩展到其他数字账本的支持。在结束时,API 将提供对任何受支持的区块链平台使用单个应用程序编程接口,无论何种技术和编程语言中使用的公共访问。


Stefano Tempesta瑞士中的 Microsoft Dynamics 365 社区是有关 AI 和业务应用程序,以及分会领导者的双精度 MVP 和 Microsoft 区域总监。Tempesta 是一名讲师的课程有关 Dynamics 365、 区块链和机器学习,并在国际 IT 会议,包括 Microsoft Ignite 和技术大会上发表演讲。他成立了 Blogchain 空间 (blogchain.space),有关区块链技术博客的 MSDN 杂志 》 和 MS Dynamics 世界中,将写入,并将发布 Azure AI 库中的机器学习试验 (gallery.azure.ai)。

衷心感谢以下技术专家:Jonathan Waldman


在 MSDN 杂志论坛讨论这篇文章