🎉 领域模型即服务 | Wow 2.11.2 发布
基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
领域驱动 | 事件驱动 | 测试驱动 | 声明式设计 | 响应式编程 | 命令查询职责分离 | 事件溯源
更新内容
新增 事件补偿 —— 群机器人(企业微信) 通知 🎉🎉,提升事件补偿处理效率!!!
- 特性: 分布式补偿调度器(
CompensationScheduler
) 支持自定义配置 - 特性: 新增
@Retry
注解 API,以支持更友好的客户端重试策略配置 - 特性:
MessageFunction
API 支持获取函数注解 - 特性:
CompensationFilter
支持@Retry
注解
群机器人(企业微信) 通知
重试执行失败通知 | 补偿成功通知 |
---|---|
快速开始
使用 Wow 项目模板快速创建基于 Wow 框架的 DDD 项目。
特性概览
架构图
性能测试 (Example)
- 测试代码:Example
- 测试场景:加入购物车、下单
- 命令发送等待模式(
WaitStrategy
):SENT
、PROCESSED
部署
测试报告
加入购物车
命令等待策略(
WaitStrategy
)为SENT
模式,加入购物车命令(AddCartItem
)写请求 API 经过 2 分钟的压测,平均 TPS 为 59625,峰值为 82312,平均响应时间为 29 毫秒。
命令等待策略(
WaitStrategy
)为PROCESSED
模式,加入购物车命令(AddCartItem
)写请求 API 经过 2 分钟的压测,平均 TPS 为 18696,峰值为 24141,平均响应时间为 239 毫秒。
下单
命令等待策略(
WaitStrategy
)为SENT
模式,下单命令(CreateOrder
)写请求 API 经过 2 分钟的压测,平均 TPS 为 47838,峰值为 86200,平均响应时间为 217 毫秒。
命令等待策略(
WaitStrategy
)为PROCESSED
模式,下单命令(CreateOrder
)写请求 API 经过 2 分钟的压测,平均 TPS 为 18230,峰值为 25506,平均响应时间为 268 毫秒。
事件源
可观测性
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 |
---|---|---|
加载聚合
聚合状态流
发送命令
命令与事件流
事件补偿
用例图
执行时序图
Dashboard

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
数禾使用 Knative 加速 AI 模型服务部署丨KubeCon China 2023
作者:李鹏(阿里云)、魏文哲(数禾科技), 此文基于 KubeCon China 2023 分享整理 摘要 AI 服务的数据、训练、推理等都需要消耗大量的计算资源以及运维成本,在数禾科技的金融业务场景下,模型存频繁迭代,线上也会同时部署多个版本的模型用于评估模型线上的真实效果,资源成本高。如何在保证服务质量基础之上提升 AI 服务运维效率并降低资源成本具有挑战性。 Knative 是一款基于 Kubernetes 之上的开源 Serverless 应用架构,提供基于请求的自动弹性、缩容到 0 以及灰度发布等功能。通过 Knative 部署 Serverless 应用可以做到专注于应用逻辑开发,资源按需使用。因此将 AI 服务与 Knative 技术相结合可以获得更高的效率并降低成本。 当前数禾科技通过 Knative 部署 500+AI 模型服务,资源成本节约比例 60%,平均部署周期由之前的 1 天缩短至 0.5 天。 在本次分享中,我们将向您展示如何基于 Knative 部署 AI 工作负载,具体内容包括: Knative 介绍 数禾基于 Knative 的最佳实践 如何在 Kna...
- 下一篇
PHP 8.3.1 发布
PHP 8.3.1 现已发布,这是一个错误修复版本。具体更新内容包括: Core: 修复了错误GH-12758/GH-12768(ZEND_FUNC_GET_ARGS 和 ZEND_BIND_STATIC 内的 OOM 处理程序中的无效 opline)。 修复各种缺失的 NULL 检查。 修复了错误GH-12835(内部 __call 上的 call->extra_named_params 泄漏)。 修复了错误GH-12826(嵌套循环中奇怪的指针问题)。 FPM:: 修复了错误GH-12705(fpm_status_export_to_zval 中的 Segmentation 错误)。 FTP: 修复了错误GH-9348(FTP 和 SSL 会话重用)。 LibXML: 修复了 libxml2 2.12.0 的测试失败问题。 MySQLnd: 避免使用未初始化的结构。 修复了错误GH-12791(MySQLnd 调试代码中可能取消引用 NULL)。 Opcache: 修复了 JIT 错误(函数 JIT 在无效偏移错误的同时发出“Uninitialized string of...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题