程序员软件架构

Axon Framework 从入门、深入到放弃

2018-11-29  本文已影响2人  黄大海

DDD领域驱动/CQRS读写分离/ES事件溯源 这些前沿的时髦的技术理念汇聚在一次,落地到一套完整实现方案。这就是Axon

我们从ES事件溯源开始说
保存当前状态.png 保存历史事件.png 保存历史事件-快照.png
领域驱动中提到过充血/失血模型
当然DDD领域驱动/CQRS读写分离/ES事件溯源这些不是强制绑定的,可以随意一选择,下面是Axon的架构图:
axon-overview.png

下面我们用axon来实践开发一个游戏(代码使用的是Axon4.0)

首选我们创建一个领域对象——玩家Player
@Aggregate
public class Player{
    @AggregateIdentifier
    private String id;

    private String name;//名字
    
    private PlayerStatus status;//状态
    
    @CommandHandler
    public Player(CreatePlayerCmd cmd) {
            AggregateLifecycle.apply(new PlayerCreatedEvent(
                IdentifierFactory.getInstance().generateIdentifier()
                , cmd.getPlayerName(), new Date()));
    }
    
    @EventSourcingHandler
    private void on(PlayerCreatedEvent event) {
         this.id = event.getId();
        this.name = event.getPlayerName();
        this.status = PlayerStatus.ACTIVE;
    }

}
接着我们实现一个随着时间自然消耗的功能
EventSourcingHandler
    private Date lastSustainLivingDate;//上次维持生存的计算时间节点
    
    @CommandHandler
    public void handle(SustainLivingCmd cmd){
         AggregateLifecycle.apply(new SustainLivingEvent(cmd.getTiggerDate(), lastSustainLivingDate));
    }

    @EventSourcingHandler
    protected void on(SustainLivingEvent event) {
        this.lastSustainLivingDate = event.getTriggerDate();
    }

PlayerEntry保存了所有玩家的列表幷提供查询,它监听PlayerCreatedEvent
@Component
public class PlayerEntryListener {
    @Autowired
    private PlayerEntryRepository playerEntryRepository;
    
    @EventHandler
    public void on(PlayerCreatedEvent event) {
        PlayerEntry playerEntry = new PlayerEntry();
        playerEntry.setId(event.getId());
        playerEntry.setName(event.getPlayerName());
        playerEntryRepository.save(playerEntry);
    }
}
Command执行过程:
Saga最终一致性,补偿机制。
说说其他实现困难的情况

取其思想,寻找替代

在交易中的订单模型,本质上就是ES中的Event. 账户余额是用订单累加出来的。只不过订单不止记录事件。还用来记录更新审核状态,系统状态,事务状态等,不那么纯粹。通过订单回溯账户状态是个人工过程而不是自动的。
Command模型配合只insert没有update的操作,可以在高并发下实现无锁处理。这个可以通过Kafka。或者数据库先插入,后异步读取处理的方式来实现。
充血模型是Axon的一个特色。不过并不难实现。通过自定义一个SpringCloud LoadBalancer Rule 实现哈希一致也可以实现。另外传统的失血模型使用无状态服务更简单,它可以在数据库层面通过一致性hash来存储数据,比如mongodb。对于订单这样的单一记录低频操作完全可以处理。对于同一记录的高频处理Axon也是有其优势的,不过Akka可能也是不错的选择
Saga异常难写,在网络异常,幂等,重试方面并不友好

总结:DDD领域驱动/CQRS读写分离/ES事件溯源,这些思想都很棒,但是并不用拘泥于特定的实现。Axon对于学习这些概念具有非常大的帮助,但是在实践的过程中幷不高效、灵活

上一篇 下一篇

猜你喜欢

热点阅读