Xtext/Sculptor框架类似JdonFramework,提供一个事件驱动特性,他们项目组基于Sculptor开发了EDA事件驱动架构 CQRS模式的拍卖案例。
在线拍卖系统,接受大量的拍卖,简单模型如下(看懂下面代码需要DDD基础):
ValueObject Bet { String betOfferId String customerId Double amount Repository BetRepository { save; } } Service BettingEngine { inject @BetRepository placeBet(@Bet bet); }
|
BettingEngine 处理这些拍卖然后存储信息。如果存在下面需求:
客户A已经完成多少拍卖?
哪些客户出了最高价?
出价最高的前10名有哪些?
当然,普通开发者会认为很容易,只要基于拍卖引擎开发多个查询即可,但是问题来了:
1.性能差:领域模型并没有为各种查询优化。
2.不具有可伸缩性:单个集中式数据库将成为瓶颈。
3.难于改变:在一个单一系统中融入太多功能。
CQRS(Command-Query Responsibility Segregation)能够将命令(修改数据)和查询(读取数据)
分离,将报表查询和业务领域处理保存更新数据两种职责分离。Command处理的结果将通过事件发送到查询子系统.
当一个拍卖发生后,我们发送领域事件Domain events。
DomainEvent BetPlaced { - Bet bet }
Service BettingPublisher { publishEvent(@BetPlaced betEvent) publish to jms:topic:bet; //发送消息 }
|
以上代码是command这边实现,下面来看看Query查询这里实现,当然要接受事件了。
首先,我们要看看查询功能实现,假设有一个客户来查询他的拍卖信息:
Module customer { Consumer BettingConsumer { inject @CustomerStatisticsRepository subscribe to jms:topic:bet //注意接受JMS消息 } Service BettingQueryService { getHighBetters => CustomerStatisticsRepository.findHighAverageCustomers; } Entity CustomerStatistics { gap String customerId key int numberOfBets double averageAmount index Repository CustomerStatisticsRepository { findByKey; save; List<@CustomerStatistics> findHighAverageCustomers(double limit); protected findByCondition; } } }
|
Query这边接受到Command那里发出已经进行拍卖的事件以后,就直接可以到仓储中查询,获取新的纪录。
本案例源代码下载
源码是以MongoDB为持久层,使用ActiveMQ 作为事件中线。
[该贴被admin于2010-09-13 09:04修改过]