怎样将微服务和无服务器相结合?用新型事件驱动型架构CQRS!

本文是将介绍如何在微服务中实施CQRS模式,并深入探讨为什么无服务器和这种类型的系统无比契合。在最后,将介绍一个使用Spring Cloud Stream实施CQRS的参考应用。

什么是事件驱动型架构?

事件驱动型架构会优先处理领域事件,但这种架构已经逐渐被淘汰。

我们日常使用的一个示例是前端应用。在如今使用的Web浏览器中,事件的处理方法是捕获用户表单的输入数据,而连接到页面元素的事件将由一个显式映射函数来处理,在触发时在用户界面应用对状态的更改。

最近,随着微服务的广泛普及,人们对如何在分布式后端系统中利用事件驱动技术重新产生了兴趣。

CQRS

如今,事件驱动型架构中最热门的实践之一叫做CQRS,全称是命令查询责任分离。CQRS是一种架构风格,能让您使用不同模型来更新和读取领域数据。

CQRS的基本理念是,您用来更新和读取数据的模型要相互分离是很自然的事情。上图描述了这种基本思想。

CQRS之所以在事件驱动型架构中如此受欢迎,是因为作为输入的领域事件与其所属的领域模型在结构上有所差异。以下面这个代表一个帐户的领域模型对象为例。

示例1.帐户整合

  1. "createdAt":1481351048967, 
  2. "lastModified":1481351049385, 
  3. "userId":1, 
  4. "accountNumber":"123456"
  5. "defaultAccount"true
  6. "status":"ACCOUNT_ACTIVE" 

当某个服务想查询帐户时,就会使用该模型。那么,如果我们要将状态更新为ACCOUNT_SUSPENDED,该怎么办?通常,只需简单更新领域对象的状态字段即可。现在,如果我们想使用领域事件来更新状态,该怎么办?由于领域对象在结构上与事件不同,我们需要一个可将不同模型作为命令接受的API。

以下代码段是将帐户状态从ACCOUNT_ACTIVE转换为ACCOUNT_SUSPENDED的领域事件。

示例2.帐户事件

  1. "createdAt":1481353397395, 
  2. "lastModified":1481353397395, 
  3. "type":"ACCOUNT_SUSPENDED"
  4. "accountNumber":"123456" 

要处理此领域事件并将更新应用到查询模型,我们必须有接受命令的API。该命令将包含领域事件的模型,并使用模型来处理对帐户查询模型的更新。

将命令模型与查询模型相分离是对CQRS最简单的解释。我们如今常见的复杂性更多地与实施类型有关,将模式应用到微服务时尤为如此。

CQRS和微服务

如果CQRS与微服务相结合,毫不夸张地说,情况就变得有点复杂了。我们来看看使用Spring Boot实施CQRS的“简单”微服务是什么样。

上图是CQRS模式实施的简略图示。图中,我们将一个微服务分为命令端、查询端和事件处理器,这三个部分可以相互独立地部署。

命令端

本示例中的命令端提供了REST API,可接受通过HTTP发送的请求。请求采取命令的形式,可以驱动对微服务所拥有的领域数据的状态更改。简单来说,对领域数据的任何写入都将以命令形式从API请求流出,处理导致数据库发生更改的操作。