浅析CQRS的应用部署

 

CQRS,中文翻译命令和查询职责分离,它是一种架构,不只能够从数据库层面实现读写分离,在代码层面上也是推荐读写分离的。在接口上能够更为简单html

 

 

 

命令端定义git

 

ICommandResult Execute(ICommand command)github

 

查询端定义数据库

 

IQueryResult Fetch(IQuery query)服务器

 

 

 

它的好处是CQ每端对外只有一个接口,职责单一。带来的不便就是要定义好多命令(Command)和查询(Query)对象。但相比定义好多个接口我的以为仍是这样的方式更好。架构

 

CQRS不是一个特别炫丽的架构,我以为他更多的是为了解决数据显示的复杂性。在实际项目中,每每是要查询的数据很是复杂和多样性(也许你并不认同),这样就能够针对查询定义相对须要的ReadModel,也能够设计多个有针对性的读库。并发

 

 

 

当咱们的应用程序开发完以后就须要发布部署了,在部署以前你的应用程序须要有个宿主能够对外提供服务,它能够是WebService,Wcf,WebApi等等。负载均衡

 

 

 

单机

 

 

 

单机是一个最简单的部署方式,优势是维护和部署起来很方便, 缺点是一旦宕机你的整个服务将不可用,处理能力有限,更新应用程序可能要中止服务。异步

 

 

 

集群

 

最简单的方式是部署多个单机,利用DNS轮询就能够实现简单的负载均衡,这种方案的缺点就是存在会话丢失,这是由于上一次的会话是在服务器1上,可能下一次的会话DNS就会将域名指向服务器2上,能够采用Cookie或者其余方案解决这一问题。还有就是这一集群方式在处理并发上难度较大,固然也能够采用乐观锁和数据库的悲观锁机制,不过这会带来性能问题。分布式

 

 

 

 

 

 

上图只是对单机集群的一种扩展,Connection Manager负责管理与客户端的链接及请求,而后将具体的命令和查询转发到具体的Server,以达到负载均衡的目的,同时它能够将处理相同命令的请求路由到同一个服务器上,能够初步解决并发问题。这种方案也有点相似ngixn,缺点就是带宽压力较大

 

 

 

分布式

 

 

上图的部署方式将命令和查询服务严格区分开来,利用消息队列达到流量削锋、应用解藕和异步处理的目的。命令服务接收到命令后将其发送到Kafka,将相同类型的命令发送到同一topic中,再根据Key分发到不一样的partition上,利用Kafka的Rebalance动态添加消费服务,这样的话就能够当请求过多时增长服务,闲时减小服务,很是灵活。

 

我的以为这样的部署有相似微服务,在此基础上还能够分离出ValidationService和AuthenticationService等,如CommandService接收到命令后经过验证服务后再发送到Kafka中,同时也是将软件层面的AOP替换成服务层面,每一个CommandConsumer像是一个黑盒,外部没法访问。

 

简单的示例能够参考 https://github.com/imyounghan/umizoo/tree/master/src/Samples

 

 

 

 

 

上图是对图2和图3的一个整合,利用了各自的优势。还有一种方案就是Connection Manager提供给客户端一个可用的CommandService或QueryService与客户端进行直连,这样能够避免全部的请求都要通过Connection Manager,减轻Connection Manager的带宽压力,能够参照P2P的思路。

 

 

 

采用了分布式后会致使服务增多,问题也会增多,管理起来也会变得复杂,能够借助Zookeeper来管理监控这些服务。总之分布式状况下要考虑的问题会有不少,本文也无逐一续清,须要掌握的知识点也较多。

相关文章
相关标签/搜索