领域建模即微服务开发 | Wow 2.10.0 发布
基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
领域驱动 | 事件驱动 | 测试驱动 | 声明式设计 | 响应式编程 | 命令查询职责分离 | 事件溯源
🎉 更新内容 🎉
新增 事件补偿 模块,以支持事件自动补偿!
- 重构: 事件补偿器(
EventCompensator
)API - 重构:
CommandMessage
/DomainEvent
/ProcessorInfoData
移动到api
模块 - 依赖: 升级
com.google.devtools.ksp:symbol-processing-api
v1.9.21-1.0.16
- 特性: 新增聚合ID转换器(
AggregateIdConverter
) - OpenAPI - 特性: 新增事件补偿模块
- 特性: 支持补偿过滤器(
CompensationFilter
),用于发送领域事件处理异常处理结果 - 特性: 支持自动配置事件补偿客户端模块
- 特性: 新增事件补偿模块 CI 测试
- 特性: 支持事件补偿服务端 Docker 镜像发布
- 特性: 支持补偿规范(
CompensationSpec
)配置 - 重构: 将基于时间的分片替换为
sipHash64
分片,以防止相同聚合ID分布到不同分区导致合并失败 - ClickHouse (ETL)
快速开始
使用 Wow 项目模板快速创建基于 Wow 框架的 DDD 项目。
特性概览
架构图
性能测试 (Example)
- 测试代码:Example
- 测试场景:加入购物车、下单
- 命令发送等待模式(
WaitStrategy
):SENT
、PROCESSED
部署
测试报告
加入购物车
WaitStrategy
:SENT
WaitStrategy
:PROCESSED
下单
WaitStrategy
:SENT
WaitStrategy
:PROCESSED
事件源
可观测性
OpenAPI (Spring WebFlux 集成)
自动注册 命令 路由处理函数 (
HandlerFunction
) ,开发人员仅需编写领域模型,即可完成服务开发。
测试套件:80%+ 的测试覆盖率轻而易举
Given -> When -> Expect .
前置条件
- 理解 领域驱动设计:《实现领域驱动设计》、《领域驱动设计:软件核心复杂性应对之道》
- 理解 命令查询职责分离(CQRS)
- 理解 事件源架构
- 理解 响应式编程
Example
订单服务(Kotlin)
银行转账(JAVA)
单元测试套件
80%+ 的测试覆盖率轻而易举。
Given -> When -> Expect .
Aggregate Unit Test (AggregateVerifier
)
internal class OrderTest { @Test private fun createOrder() { val tenantId = GlobalIdGenerator.generateAsString() val customerId = GlobalIdGenerator.generateAsString() val orderItem = OrderItem( GlobalIdGenerator.generateAsString(), GlobalIdGenerator.generateAsString(), BigDecimal.valueOf(10), 10, ) val orderItems = listOf(orderItem) val inventoryService = object : InventoryService { override fun getInventory(productId: String): Mono<Int> { return orderItems.filter { it.productId == productId }.map { it.quantity }.first().toMono() } } val pricingService = object : PricingService { override fun getProductPrice(productId: String): Mono<BigDecimal> { return orderItems.filter { it.productId == productId }.map { it.price }.first().toMono() } } aggregateVerifier<Order, OrderState>(tenantId = tenantId) .inject(DefaultCreateOrderSpec(inventoryService, pricingService)) .given() .`when`(CreateOrder(customerId, orderItems, SHIPPING_ADDRESS, false)) .expectEventCount(1) .expectEventType(OrderCreated::class.java) .expectStateAggregate { assertThat(it.aggregateId.tenantId, equalTo(tenantId)) } .expectState { assertThat(it.id, notNullValue()) assertThat(it.customerId, equalTo(customerId)) assertThat(it.address, equalTo(SHIPPING_ADDRESS)) assertThat(it.items, equalTo(orderItems)) assertThat(it.status, equalTo(OrderStatus.CREATED)) } .verify() } @Test fun createOrderGivenEmptyItems() { val customerId = GlobalIdGenerator.generateAsString() aggregateVerifier<Order, OrderState>() .inject(mockk<CreateOrderSpec>(), "createOrderSpec") .given() .`when`(CreateOrder(customerId, listOf(), SHIPPING_ADDRESS, false)) .expectErrorType(IllegalArgumentException::class.java) .expectStateAggregate { /* * 该聚合对象处于未初始化状态,即该聚合未创建成功. */ assertThat(it.initialized, equalTo(false)) }.verify() } /** * 创建订单-库存不足 */ @Test fun createOrderWhenInventoryShortage() { val customerId = GlobalIdGenerator.generateAsString() val orderItem = OrderItem( GlobalIdGenerator.generateAsString(), GlobalIdGenerator.generateAsString(), BigDecimal.valueOf(10), 10, ) val orderItems = listOf(orderItem) val inventoryService = object : InventoryService { override fun getInventory(productId: String): Mono<Int> { return orderItems.filter { it.productId == productId } /* * 模拟库存不足 */ .map { it.quantity - 1 }.first().toMono() } } val pricingService = object : PricingService { override fun getProductPrice(productId: String): Mono<BigDecimal> { return orderItems.filter { it.productId == productId }.map { it.price }.first().toMono() } } aggregateVerifier<Order, OrderState>() .inject(DefaultCreateOrderSpec(inventoryService, pricingService)) .given() .`when`(CreateOrder(customerId, orderItems, SHIPPING_ADDRESS, false)) /* * 期望:库存不足异常. */ .expectErrorType(InventoryShortageException::class.java) .expectStateAggregate { /* * 该聚合对象处于未初始化状态,即该聚合未创建成功. */ assertThat(it.initialized, equalTo(false)) }.verify() } }
Saga Unit Test (SagaVerifier
)
class CartSagaTest { @Test fun onOrderCreated() { val orderItem = OrderItem( GlobalIdGenerator.generateAsString(), GlobalIdGenerator.generateAsString(), BigDecimal.valueOf(10), 10, ) sagaVerifier<CartSaga>() .`when`( mockk<OrderCreated> { every { customerId } returns "customerId" every { items } returns listOf(orderItem) every { fromCart } returns true }, ) .expectCommandBody<RemoveCartItem> { assertThat(it.id, equalTo("customerId")) assertThat(it.productIds, hasSize(1)) assertThat(it.productIds.first(), equalTo(orderItem.productId)) } .verify() } }
设计
聚合建模
Single Class | Inheritance Pattern | Aggregation Pattern |
---|---|---|
加载聚合
聚合状态流
发送命令
命令与事件流
Saga - OrderProcessManager (Demo)

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
🔥smart-mqtt v0.34 发布,600W/s 的性能收官 2023
1、smart-mqtt 简介 smart-mqtt,是 smartboot 组织下面向物联网的首款解决方案,它使用 Java 语言开发,提供高效、可靠的 MQTT Broker 服务。 smart-mqtt 的独特优势在于大量设备接入的情况下,仍能保持低延迟和高吞吐量,满足物联网领域严苛的实时性需求。同时,smart-mqtt 为了最大限度地节省硬件成本,采用了高度优化的资源管理策略,降低了系统运行时的 CPU 和内存占用,使企业在保持高性能的同时,大幅降低运维成本。 另外,mqtt 协议天然适合 IM 场景,需要打造企业级 IM 应用,smart-mqtt 同样是一个非常好的选择。 smartboot 开源组织,一个容易被误认为是在 “重复造轮子” 的低调组织。曾获得2020 年度 OSC 中国开源项目「优秀 Gitee 组织 」荣誉。 该组织内的明星项目包括: smart-socket 历时 5 年精炼出 2 千多行代码,轻松实现百万级长连接的 AIO 通信框架。 smart-http 基于 smart-socket 实现的 HTTP/1.1 web 服务。 smart-serv...
- 下一篇
openKylin 2.0 揭秘 | UKUI 4.10 双钻设计,有颜有质!
UKUI 4.10新版本将伴随openKylin 2.0的发布和大家见面,今天让我们一起来看看,与之前版本相比,UKUI 4.10在设计上有哪些亮点升级。 一、背景概述 UKUI桌面环境经过多年迭代虽已取得阶段性成果,但在习惯继承和易用性等用户体验方面仍有待改善。因此,在UKUI 4.10新版本中,UKUIDesign SIG对UKUI桌面环境中的六个核心模块进行设计升级,并首次引入“双钻设计模型”方法论,将设计工作分成前期研究和后期设计两个阶段,如下图所示: UKUIDesign SIG从产品需求、用户调研和设计反思三方面提炼问题中的关键词,取其共性作为UKUI4.10设计方向。从提效和继承两个维度,对桌面环境中使用频率高且重要的六个核心模块进行设计升级。 二、亮点升级 因此,在延续“视觉聚焦、交互轻松”的设计理念和寻光整体设计风格的基础上,依据调研分析和用户反馈,UKUI 4.10新版本开始菜单、侧边栏、文件管理、任务栏、多任务视图、登录&锁屏等模块在界面布局和用户交互体验上进行了以下亮点升级。 1、开始菜单 UKUI 4.10 开始菜单优化新装应用消失机制,从用户习...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6