这是一个使用Spring Boot和Axon以及Docker构建的Event Sorucing源码项目,技术特点:
1.使用Java 和Spring Boot实现微服务;
2.使用命令和查询职责分离 (CQRS) 和 Event Sourcing (ES) 的框架Axon Framework v2, MongoDB 和 RabbitMQ;
3.使用Docker构建 交付和运行;
4.集中配置和使用Spring Cloud服务注册;
5.使用Swagger 和 SpringFox 提供API文档
工作原理:
这个应用使用CQRS架构模式构建,在CQRS命令如ADD是和查询VIEW(where id=1)分离的,在这个案例中领域部分代码已经分离成两个组件:一个是属于命令这边的微服务和属性查询这边的微服务。
微服务是单个职责的功能,自己的数据存储,每个能彼此独立扩展部署。
属于命令这边的微服务和属性查询这边的微服务都是使用Spring Boot框架开发的,在命令微服务和查询微服务之间通讯是事件驱动,事件是通过RabbitMQ消息在微服务组件之间传递,消息提供了一种进程节点或微服务之间可扩展的事件载体,包括与传统遗留系统或其他系统的松耦合通讯都可以通过消息进行。
请注意,服务之间不能彼此共享数据库,这是很重要,因为微服务应该是高度自治自主的,这样反过来有助于服务能够彼此独立地扩展伸缩规模。
CQRS中命令是“改变状态的动作”。命令的微服务包含所有领域逻辑和业务规则,命令被用于增加新的产品或改变它们的状态,这些命令针对某个具体产品的执行会导致事件Event产生,这会通过Axon框架持久化到MongoDB中,然后通过RabbitMQ传播给其他节点进程或微服务。
在event-sourcing中,事件是状态改变的原始记录,它们用于系统来重新建立实体的当前状态(通过重新播放过去的事件到当前就可以构建当前的状态),这听上去会很慢,但是实际上,事件都很简单,执行非常快,也能采取‘快照’策略进行优化。
请注意,在DDD中,实体是指一个聚合根实体。
上面是命令这边的微服务,下面看看查询这边的微服务:
查询微服务一般扮演一种事件监听器和视图角色,它监听到命令那边发出的事件,然后处理它们以符合查询这边的要求。
在这个案例中,查询这边只是简单建立和维持了一个 ‘materialised view’或‘projection’ ,其中保留了产品的最新状态,也就是产品id和描述以及是否被卖出等等信息,查询这边能够被复制多次以方便扩展,消息可以保留在RabbitMQ队列中实现持久保存,这种临时保存消息方式可以防止查询这边微服务当机。
命令微服务和查询微服务两者都有REST API,提供外界客户端访问。
下面看看如何通过Docker运行这个案例,需要 Ubuntu 16.04:
1.Docker ( v1.8.2)
2.Docker-compose ( v1.7.1)
在一个空目录,执行下面命令下载docker-compose:
$ wget https://raw.githubusercontent.com/benwilcock/microservice-sampler/master/docker-compose.yml
注意:不要更改文件名称。
启动微服务:只是简单一个命令:
$ docker-compose up
你会看到许多下载信息和日志输出在屏幕上,这是Docker image将被下载和运行。一共有六个docker,分别是: ‘mongodb’, ‘rabbitmq’, ‘config’, ‘discovery’, ‘product-cmd-side’, 和 ‘product-qry-side’.
使用下面命令进行测试增加一个新产品:
$ curl -X POST -v --header "Content-Type: application/json" --header "Accept: */*" "http://localhost:9000/products/add/1?name=Everything%20Is%20Awesome"
查询这个新产品:
$ curl http://localhost:9001/products/1