微服务实战(五):落地微服务架构到直销系统(构建高性能大并发系统)前端
在现代系统中,特别是互联网软件,一般会涉及到大量用户的并发访问,咱们的系统必定要在架构上支持高性能、大并发的访问。一个高性能的系统一般由不少的方面组成,包括数据库高性能、Web服务器高性能、负载均衡、缓存、软件架构等。咱们这篇文章先从软件开发架构的角度做为切入点来介绍如何构建高性能的系统。数据库
传统架构性能的问题缓存
咱们先来看看DDD经典架构中,在多用户、大并发访问的状况下,对性能产生不利影响的因素。先来看看简单架构图:服务器
1.一般会在当前界限上下文中只有一个领域模型,这个领域模型既会用于领域逻辑,同时也会用于持久化。
2.领域模型既会用于用例、也会用于查询。
3.当前界限上下文一般只会有一个WebApi项目,这个项目中不一样的Action Api用于不一样的功能,有查询的,有用例的。微信
从上面几点你们能够看出,有如下几个缘由带来性能的瓶颈:架构
1.上下文的查询和用例经过一个模型来作,对应到数据库来说,就是增、删、改、查针对同一个数据库的相关表,经过阻塞会形成性能问题;虽然经过创建好的索引能够进行缓解,但解决问题不完全。并发
2.领域模型一般是根据业务须要进行设计的,也就是用于用例。若是用于查询需求的话,可能会链接多个业务表才能完成查询,查询性能出现问题。负载均衡
3.一般经典DDD是完成领域逻辑后,经过应用服务协调领域逻辑与仓储来将领域对象持久化到数据存储中,而后经过WebApi返回用户结果。若是领域复杂,用户并发量大的话,这个过程反馈到前端有必定的时间,用户体验很差。ssh
4.当前界限上下文是一个WebApi项目,不管是用例仍是查询;这样也没法对性能进行扩展,好比用例的在一些主机上,查询的在另外一些主机上。微服务
为了有效的解决上述出现的性能问题,业界总结了一种架构风格,也就是CQRS(命令查询职责分离)。经过CQRS的理念,能够有效的提升系统对大并发的支持。
命令指的是要更改对象状态的行为,对系统有反作用;查询指的是不更改对象状态的行为,对系统无反作用。其实CQRS不只仅用于大并发的处理,在平常开发中,其实也是能够利用这种理念的。
命令与查询混在一块儿的状况:
private int Add(int a,int b)
{ int result = a + b; return result; }
从上面代码能够看出,更改状态与查询是混在一块儿的;咱们能够改形成命令与查询分离的方式:
private int result;
private void Add(int a,int b) { result = a + b; } private int QueryResult() { return result; }
基于上述代码的思路与经典DDD架构的问题,咱们就引入CQRS架构风格来解决性能问题。
CQRS架构
咱们先来看看CQRS总体的架构图,而后再说它是怎么解决性能问题的。
咱们来看看总体架构图的流程以及它是如何解决性能问题的:
1.首先能够看到命令与查询走不一样的WebApi服务,这样能够将更改系统状态的行为与查询的行为作很好的隔离,并能够部署微服务到不一样的服务器上,固然还能够经过NLB作进一步的扩展。
2.命令端的WebApi并不直接处理调用用例完成,而是接收到用户命令时,将命令消息发布到消息总线,而后马上返回一个操做信息给用户,这样用户体验很好,不须要等待业务逻辑完成与持久化完成。
3.命令处理器WebApi从消息队列侦听到消息,而后进行处理,处理的主要内容是完成领域逻辑调用,直接添加事件数据到事件存储中。这里须要注意的是,并非持久化到业务数据库中。首先完成领域逻辑调用,能够获得用例最终正确的领域对象,而后存储事件时,存储此次领域对象的状态,而且是直接添加。这样作的好处有:一是加快持久化,二是可以保存领域对象每次变化的信息,将来能够用于历史追踪、事件溯源与最终一致性。
4.命令处理器将领域对象发送到消息总线中,事件处理器会侦听队列,并最终将消息信息涉及到的领域对象持久化到业务数据库中。
5.在查询WebApi中,能够直接查询业务库,若是业务库并不适合多表链接查询时,能够再单独作个拉平的为查询提供服务的查询库。查询库的内容能够经过业务库更新成功后,发布消息到另外一个队列中,而后经过处理器来处理这些数据到查询库中。
QQ讨论群:309287205 微服务实战视频请关注微信公众号:msshcj