通过一组RESTful API暴露CQRS系统功能

命令和查询责任分离(CQRS)是由Greg Young提出的一种将系统的读(查询)、写(命令)操作分离为两种独立子系统的架构模式。命令通常是异步执行的,并存储在一个事务型数据库中,而读操作则通常是最终一致的,并且数据来自于解正规化的视图。

本文在此提出并为读者展示一种为CQRS系统创建一套RESTful API的方式。这种方式结合了HTTP的语义、REST API基于资源的风格,并能够处理分布式计算的某些问题,例如最终一致性和并发性。

此外我们还提供了一套原型API,它建立于Greg Young编写的m-r CQRS原型之上,后者也被称为SimplestPossibleThing。m-r可以认为是CQRS原型的事实标准,它鼓舞了许多团队采用并创建CQRS系统。虽然这个m-r原型很简单,但它已经能够展示在现实世界中使用RESTful CQRS系统的某些机遇和挑战了。

我们在将下一部分审阅m-r的领域模型,随后对相关特性的API设计进行一些探索。最后,我们将对一些所做的选择展开讨论,并且讨论一些RESTful m-r的概念和理论内容。

m-r领域

m-r模型是一个经过简化的库存管理系统的领域模型,你可以创建新库存物品(假设它是某种类型的产品),重命名或取消激活(即逻辑删除)它们。被取消激活的物品将不再为用户所见,而所有活动的物品都可以被获取,并且能够看到每个物品的所有细节。你也能够增加或减少这些库存物品,指定所加入或减少的物品数据。换句话说,在建立库存量之后,就可以开始使用这个系统了。

用户将通过同步的查询来查看物品列表或是物品细节,对于物品状态的修改将通过命令来实现。在现实世界中,命令应该是异步执行的,但由于代码中使用了内存中的事件总线(Event Bus)及事件处理函数,因此在最终实现中命令都是同步执行的。

m-r模型实现了CQRS:命令和查询被分别存储在不同的地方,并且各自由系统中完全不同的部分进行处理。

除了CQRS之外,m-r也使用了事件溯源(Event Sourcing)作为它的持久化机制。在这种方式中,对于领域模型的修改会被捕获为一系列的事件,这些事件会按照它们被调用的顺序存储起来。为了获取某个模型的当前状态,需要将所有事件按照它们发生的顺序进行重播。换句话说,模型中实体的状态信息是不会被持久化的。举例来说,如果我们创建了一个库存物品,随后将它重命名两次,那么我们将会得到一个InventoryItemCreated事件和两个InventoryItemRenamed事件,这些事件都会被保存在事件存储(Event Store)中。

事件是连续的,并且每个事件都带有一个版本号,用以在并发时进行检查。举例来说,如果某个库存物品在版本2的基础上进行重命名,但正好有另一个重命名发生在同一个物品上,并使它的当前版本变为3,那么这种情况就会导致并发异常。

命令与领域事件通常是一对一的关系,当调用了某个命令之后,领域模型会发起并存储一个事件。领域事件是事件溯源的基石,它和跨多个边界上下文(bounded context)的事件不同,往往粒度更细,并且只包括所需的最小数量的信息。因此,它并不是一个适合于在不同的边界上下文之间进行集成的工具。除了使用一个进程内的事件总线之外,m-r还用到了一个内存中的事件存储。这个存储本质就是一个哈希表,它使用模型的id作为键,并且持续跟踪模型中发生的任何事件。

如欲了解CQRS和事件溯源的更多信息,你可以阅读Greg Young的这本迷你书。

时间: 2024-08-21 23:29:53

通过一组RESTful API暴露CQRS系统功能的相关文章

通过一组RESTful API暴露CQRS系统功能(转)

http://kb.cnblogs.com/page/506897/  

如何更好的设计RESTful API

当您的数据模型已开始稳定,您可以为您的网络应用程序创建公共API. 你意识到,很难对你的API进行重大更改,一旦它发布,并希望尽可能得到尽可能多的前面. 现在,互联网对API设计的意见有很多. 但是,因为没有一个广泛采用的标准在所有情况下都有效,所以你前面有一堆选择:你应该接受什么格式? 你应该如何认证? 你的API是否应该版本化?构建API是您可以做的最重要的事情之一,以提高您的服务的价值. 通过使用API,您的服务/核心应用程序有可能成为其他服务增长的平台. 看看当前巨大的科技公司:Face

RESTful API 设计最佳实践

Web API 近几年变得越来越火,而简洁的 API 设计在多后端系统交互应用中也变得尤为重要.通常,会使用 RESTful API 来作为我们的 Web API .本文介绍了几种简洁 RESTful API 设计的最佳实践. 使用的名词而不是动词 使用名词来定义接口 资源 GET PUT POST DELETE 一组资源的URI,比如http://www.waylau.com/resources/ 列出 URI,以及该资源组中每个资源的详细信息(后者可选). 使用给定的一组资源替换当前整组资源

用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一

目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 RESTful API 的优势 REST 约束 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 Flask 来写个轻博客 (3) - (M)VC_连接 MySQL 和 SQLAlchemy 用 Flask 来写个轻博客 (4) - (M)VC_创建数据模型和表 用 Flask 来写个轻博客 (5) - (M)VC_SQ

HTTP methods 与 RESTful API

  Note GET, primarily used to select resources. Other options for an API method include: POST, primarily used to create child resources. PUT, primarily used to update existing resources (and, although not recommended, can be used to create child reso

遗留应用现代化场景:如何正确使用RESTful API

企业正在使用RESTful API来现代化其基础架构的关键方面,但是该方案怎么才能工作呢?我们为此专门采访了OpenLegacy的Zeev Avidan. 对于不堪遗留基础架构重负,并寻找出路的企业而言,应用程序接口成为越来越有吸引力的方案. Zeev Avidan,OpenLegacy的产品副总裁,探讨了使用API来现代化遗留基础架构的典型方案,讨论了在这些方案中为什么RESTful API如此重要,以及很多企业的"遗留"基础架构实际上都比他们意识到的更有价值的原因. 使用API现代

微服务架构实战:Swagger规范RESTful API

REST的引入 本文讲的是微服务架构实战:Swagger规范RESTful API,随着微服务架构的广泛流行,REST风格受到越来越多的关注.我们先来看一下REST在WIKI的定义及五大关键点: 什么是统一接口? REST要求,必须通过统一的接口来对资源执行各种操作.对于每个资源只能执行一组有限的操作.以HTTP/1.1协议为例,此协议定义了一个操作资源的统一接口,主要包括以下内容: 7个HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS HTTP头信息(

Spring Boot中使用Swagger2构建强大的RESTful API文档

由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端. 这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发.Android开发或是Web开发等.为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTf

RESTful API设计给开发人员带来怎样的未来?

业界正在逐渐承认RESTful API优于面向服务架构.但是这对于架构师和开发人员而言到底意味着什么?Tom Nolle分享了他的想法. 在模块化应用世界里,最为持久的争论莫过于面向服务架构和表述性状态转移之争了.本文探讨这样的争论带来了什么及其背后的原因. SOA已经被定性为连接组件和工作流的严格的且重量级的方案,REST则赢得了更多的赞誉.两者的特征都是简化,但是要学习RESTful API设计,架构师和开发人员必须理解SOA和REST之间的差异,学习REST和云以及微服务一起的演进,并且了