专栏首页领域驱动设计DDD实战进阶微服务实战(五):落地微服务架构到直销系统(构建高性能大并发系统)

微服务实战(五):落地微服务架构到直销系统(构建高性能大并发系统)

在现代系统中,特别是互联网软件,通常会涉及到大量用户的并发访问,我们的系统一定要在架构上支持高性能、大并发的访问。一个高性能的系统通常由很多的方面组成,包括数据库高性能、Web服务器高性能、负载均衡、缓存、软件架构等。我们这篇文章先从软件开发架构的角度作为切入点来介绍如何构建高性能的系统。

传统架构性能的问题

我们先来看看DDD经典架构中,在多用户、大并发访问的情况下,对性能产生不利影响的因素。先来看看简单架构图:

1.通常会在当前界限上下文中只有一个领域模型,这个领域模型既会用于领域逻辑,同时也会用于持久化。

2.领域模型既会用于用例、也会用于查询。

3.当前界限上下文通常只会有一个WebApi项目,这个项目中不同的Action Api用于不同的功能,有查询的,有用例的。

从上面几点大家可以看出,有以下几个原因带来性能的瓶颈:

1.上下文的查询和用例通过一个模型来做,对应到数据库来讲,就是增、删、改、查针对同一个数据库的相关表,通过阻塞会造成性能问题;虽然通过建立好的索引可以进行缓解,但解决问题不彻底。

2.领域模型通常是根据业务需要进行设计的,也就是用于用例。如果用于查询需求的话,可能会连接多个业务表才能完成查询,查询性能出现问题。

3.通常经典DDD是完成领域逻辑后,通过应用服务协调领域逻辑与仓储来将领域对象持久化到数据存储中,然后通过WebApi返回用户结果。如果领域复杂,用户并发量大的话,这个过程反馈到前端有一定的时间,用户体验不好。

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)
        {
            int result = a + b;           
        }
        private int QueryResult()
        {
            return result;
        }

基于上述代码的思路与经典DDD架构的问题,我们就引入CQRS架构风格来解决性能问题。

CQRS架构

我们先来看看CQRS整体的架构图,然后再说它是怎么解决性能问题的。

我们来看看整体架构图的流程以及它是如何解决性能问题的:

1.首先可以看到命令与查询走不同的WebApi服务,这样可以将更改系统状态的行为与查询的行为做很好的隔离,并可以部署微服务到不同的服务器上,当然还可以通过NLB做进一步的扩展。

2.命令端的WebApi并不直接处理调用用例完成,而是接收到用户命令时,将命令消息发布到消息总线,然后立刻返回一个操作信息给用户,这样用户体验很好,不需要等待业务逻辑完成与持久化完成。

3.命令处理器WebApi从消息队列侦听到消息,然后进行处理,处理的主要内容是完成领域逻辑调用,直接添加事件数据到事件存储中。这里需要注意的是,并不是持久化到业务数据库中。首先完成领域逻辑调用,可以得到用例最终正确的领域对象,然后存储事件时,存储这次领域对象的状态,并且是直接添加。这样做的好处有:一是加快持久化,二是能够保存领域对象每次变化的信息,未来可以用于历史追踪、事件溯源与最终一致性。

4.命令处理器将领域对象发送到消息总线中,事件处理器会侦听队列,并最终将消息信息涉及到的领域对象持久化到业务数据库中。

5.在查询WebApi中,可以直接查询业务库,如果业务库并不适合多表连接查询时,可以再单独做个拉平的为查询提供服务的查询库。查询库的内容可以通过业务库更新成功后,发布消息到另一个队列中,然后通过处理器来处理这些数据到查询库中。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 微服务实战(九):落地微服务架构到直销系统(回顾总结)

    这个系列我们大概写了八篇文章,将微服务的最重要的内容过了一遍。当然其中有些内容还没有涉及到,比如Docker(不是微服务架构风格中必须的)等,关于Docker我...

    用户1910585
  • 领域驱动设计-基本概念

    用户1910585
  • 微服务实战(八):落地微服务架构到直销系统(服务高可用性)

    在微服务架构风格的系统中,如果单个微服务垮掉或地址不可访问,虽然对系统的影响是有限的,但我们也必须采取一定的手段来保证每个微服务尽量可用;并且在大并发的情况下,...

    用户1910585
  • Lake Counting(POJ-2386)

    题目链接: http://poj.org/problem?id=2386 题目大意: 计算出相连的'W'有多少块 所需算法: 深度优先搜索(DFS) 主要思路:...

    llhthinker
  • Waymo获得加州首个完全自动驾驶汽车许可证

    Waymo已获得加利福尼亚州机动车辆部(DMV)的自动驾驶测试许可证,这是第一家获得许可的公司,允许公司在加州公路上测试其Chrysler Pacifica自动...

    AiTechYun
  • 战斗民族开源神器ClickHouse:一款适合于构建量化回测研究系统的高性能列式数据库(一)

    编辑部原创 编译:wally21st、 西西 未经允许,不得转载 对于一些私募、投资机构和个人来说,量化投资研究、回测离不开数据的支持。当数据量达到一定数量,如...

    量化投资与机器学习微信公众号
  • 网络流--最大流--POJ 1273 Drainage Ditches

    Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite...

    风骨散人Chiam
  • java大量数据加载时resultSetType参数的设置 TYPE_FORWARD_ONLY

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • 力扣739——每日温度

    根据每日气温列表,请重新生成一个列表,对应位置的输入是你需要再等待多久,温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。

    健程之道
  • 24.C++- 抽象类(存虚函数)、接口、多重继承

    抽象类和接口 什么是抽象类 用来表示现实世界中的抽象概念 是一种只能定义类型,而不能产生对象的类 只能被子类继承,且抽象类的相关成员函数没有完整的体现,用来被子...

    张诺谦

扫码关注云+社区

领取腾讯云代金券