atop工具

背景

1、某次收到某个应用一台机器14:32:02挂掉的报警。

2、于是一顿操作猛如虎,然后一脸懵逼:究竟是什么导致了系统挂掉!

3、于是求助了公司ops热线,发现一个好用的工具。解决了这个疑惑。这个工具就是atop。

先上一张图来加深印象:

正是从上图,得知,是有同学在14:32:02秒执行了less命名导致了系统cpu飙升。(这里先不分析为什么less会导致cpu飙升,本文主要讲解atop工具)。

现在开始介绍atop工具。

简介

 atop是一款用于监控Linux系统资源与进程的工具,它以一定的频率记录系统的运行状态,所采集的数据包含系统资源(CPU、内存、磁盘和网络)使用情况和进程运行情况,并能以日志文件的方式保存在磁盘中,服务器出现问题后,我们可获取相应的atop日志文件进行分析,其比较强大的地方是其支持我们分析数据时进行排序、视图切换、正则匹配等处理。

监控字段的含义

ATOP列:该列显示了主机名、信息采样日期和时间点

PRC列:该列显示进程整体运行情况

  1. sys、usr字段分别指示进程在内核态和用户态的运行时间
  2. #proc字段指示进程总数
  3. #zombie字段指示僵死进程的数量
  4. #exit字段指示atop采样周期期间退出的进程数量

CPU列:该列显示CPU整体(即多核CPU作为一个整体CPU资源)的使用情况,我们知道CPU可被用于执行进程、处理中断,也可处于空闲状态(空闲状态分两种,一种是活动进程等待磁盘IO导致CPU空闲,另一种是完全空闲)

  1. sys、usr字段指示CPU被用于处理进程时,进程在内核态、用户态所占CPU的时间比例
  2. irq字段指示CPU被用于处理中断的时间比例
  3. idle字段指示CPU处在完全空闲状态的时间比例
  4. wait字段指示CPU处在“进程等待磁盘IO导致CPU空闲”状态的时间比例

CPU列各个字段指示值相加结果为N00%,其中N为cpu核数。

cpu列:该列显示某一核cpu的使用情况,各字段含义可参照CPU列,各字段值相加结果为100%

CPL列:该列显示CPU负载情况

  1. avg1、avg5和avg15字段:过去1分钟、5分钟和15分钟内运行队列中的平均进程数量
  2. csw字段指示上下文交换次数
  3. intr字段指示中断发生次数

MEM列:该列指示内存的使用情况

  1. tot字段指示物理内存总量
  2. free字段指示空闲内存的大小
  3. cache字段指示用于页缓存的内存大小
  4. buff字段指示用于文件缓存的内存大小
  5. slab字段指示系统内核占用的内存大小

SWP列:该列指示交换空间的使用情况

  1. tot字段指示交换区总量
  2. free字段指示空闲交换空间大小

PAG列:该列指示虚拟内存分页情况

swin、swout字段:换入和换出内存页数

DSK列:该列指示磁盘使用情况,每一个磁盘设备对应一列,如果有sdb设备,那么增多一列DSK信息

  1. sda字段:磁盘设备标识
  2. busy字段:磁盘忙时比例
  3. read、write字段:读、写请求数量

NET列:多列NET展示了网络状况,包括传输层(TCP和UDP)、IP层以及各活动的网口信息

  1. XXXi  字段指示各层或活动网口收包数目
  2. XXXo 字段指示各层或活动网口发包数目

视图模视

1、默认视图(Generic information)

进入atop信息界面,我们看到的就是进程信息的默认视图(上图下半部分),按g键可以从其他视图跳到默认视图。以简介里的截图为例,我们可以看到PID为31085的find进程在退出前在内核模式下占用了0.45秒CPU时间,在用户模式下占用了0.10秒CPU时间,相对10分钟采样周期,CPU时间占用比例为3%,ST列表示进程状态,N表示该进程是前一个采样周期新生成的进程,E表示该进程已退出,EXC列指示进程的退出码。从进程名在“<>”符号中,我们亦可知该进程已退出。

2、内存视图(Memory consumption)

内存视图展示了进程使用内存情况,按m键可进入内存视图。如下图:

上图下半部分展示了每个进程占用的虚拟内存空间(VSIZE)、内存空间(RSIZE)大小,以及在上一个采样周期中虚拟内存和物理内存增长大小(VGROW、RGROW),MEM列指示进程所占物理内存大小。从上图的PAG列的信息,我们可以知道此时系统内存负载较高,页交换比较频繁,而且可以看出物理内存几乎完全不可用,swap分区也比较繁忙,从进程视图中VGROW和RGROW列可看出 lekker 进程占用内存量大量增长,部分进程占用的内存减少(VGROW或RGROW字段为负值),为lekker进程腾出空间。

3、命令视图(Command line)

这个对于查看具体某个命令的详细参数,很容易通过该模式下查看到。比如,我们有多个java程序,普通视图下,可能看到的只显示为java ,但通过命令模式,我们可以方便的区分出,到底是哪个java程序占用资源比较高。如下图:

4、磁盘视图

通过按键d 可以进入磁盘视图,可以查看每个进程占用IO的情况。

快捷键汇总

进入atop目录: /var/log/atop

读取atop日志文件: atop  -r  XXX

读取atop日志文件(更具时间范围): atop -r atop_20190325 -b 14:34 -e 14:35

前进翻页: t

后退翻页: T

进程列表前进翻页: ctrl + f

进程列表后退翻页: ctrl + b

按时间跳转:

 b

 Enter new time (format hh:mm):

 按hh:mm格式输入时间

进程视图:

g   —— 默认输出

m  —— 内存相关输出

d   —— 磁盘相关输出

n   —— 网络相关输出

c   —— 命令行输出

u  查看对应的用户资源使用情况

p  显示所有每个进程的所有信息占用情况(disk、mem、io)

P(大写) 正则匹配,显示所有匹配到的进程

退出atop:q

更加详细的说明:http://www.361way.com/atop/5162.html

架构师设计大纲

哪些项目必须写设计文档

DEV工作量大于等于2PD的项目必须写设计文档,建议所有项目都根据设计大纲确认一下有没有问题。

设计的坏味道

线上频繁执行SQL来修复问题

有大量的JSP后门

机制和策略不分离,任何修改都牵一发而动全身

设计大纲

按照项目研发流程设计

需求解析

分析相关方、计算收益,定义评估方法

描述背景、要解决的问题

名词及术语定义

总体设计

技术选型:涉及技术选型,需要对比候选方案的优缺点,特别要关注一个技术方案的缺点自己是否可以接受。

确定边界:系统边界、代码边界、接口边界等

确定交互流程:

  • 交互流程划分:业务交互流程、系统交互流程、模块交互流程
  • 交互流程检查点:一致性、性能
  • 策略算法相关功能:需要画出流程图

结构设计:

  • 逻辑结构:数据模型、时序模型、状态机模型;
  • 物理结构:DB;
  • 部署结构:分析依赖关系,后续要根据以来关系来撰写上线步骤

详细设计

存储设计:

  • 抽象出业务实体
  • 画出实体之间的ER关系图
  • 定义表结构,写出MySQL scheme变化
  • 考虑数据如何初始化

接口设计:

  • 接口组成:存储层接口、模块间接口、系统间接口
  • 接口应该抽象一组能力,良好的设计应该做到“机制和策略分离”,而接口应该承担分离的职责
  • 接口变化需要检查是否有兼容性问题

类图:类描述业务实体,需要描述清楚类之间的关系;类图的设计可以参考各种设计模式,

测试设计

可测性:尽量减少对环境的依赖,确定自测方法;策略算法相关的功能,需要提前想好如何获取数据、如何度量好坏;

测试范围:写明项目的影响面、确定测试范围。测试范围评估不准,会影响自测质量,进而导致联调时间偏长、QA测试时间偏长、QA测试评估不充分导致质量偏低。

测试用例:包括单元测试用例、接口测试用例、系统测试用例、面向C端的用例等

发布流程

写上线步骤:包括上线步骤、回滚步骤(必须和上线步骤相反,每一步都需要有回滚方案)、线上检查方法、应急方案(回滚或者降级);要重点检查兼容性。

上线前评估:上线时间(上线要评估对业务的影响,进而决定可行的上线时间)

阿里技术三板斧:可灰度,可监控,可回滚。

按照系统层次结构设计

存储设计

  • 抽象出业务实体
  • 画出实体之间的ER关系图
  • 定义表结构,写出MySQL scheme变化
  • 考虑数据如何初始化

API设计

构成:API可以划分为存储API、模块间API、对外API

方法:建议使用OOA、DDD等设计方法;一个良好的接口应该描述一组能力,可以尝试使用一句话来描述接口的能力。

模块设计

根据API粒度,按照服务原则,规划模块及模块关系

流程设计

  • 交互流程划分:业务交互流程、系统交互流程、模块交互流程
  • 交互流程检查点:一致性、性能
  • 策略算法相关功能:需要画出流程图

系统结构设计

  • 逻辑结构:数据模型、时序模型、状态机模型;
  • 物理结构:DB;
  • 部署结构:分析依赖关系

关键检查点和设计组成

工作量拆分

性能:

  • 存储性能:选择DB、设计表结构、设计Cache机制
  • 接口性能
  • 吞吐量
  • 数据规模

一致性:

  • 数据一致性:事务处理是否正确,是否涉及分布式数据一致性,是否需要分布式事务
  • 并发处理:锁、幂等机制等

监控

附录:设计流水账

  1. 明确交互流程:系统之间、业务、模块
  2. 交互流程关键节点:一致性、性能
  3. 底层API(对外、存储)、DB数据库设计(实体关系、scheme-SQL)
  4. 对现有系统影响范围,评估、应对方案
  5. 详细设计:接口、前端接口、类图
  6. 发布流程:兼容性、上线步骤、历史刷数
  7. 数据:增加字段如何处理,如何刷数据
  8. 用例Case(C端)
  9. 上线前前评估:吞吐量、性能、时间、数据规模
  10. 涉及状态:状态机
  11. 测试要点:TestCase、单元测试Case、自测方法、测试范围(事后用联调、QA测试状况来评估)、可测性(免环境)
  12. 业务模型、模块、层次图
  13. 工作量拆分
  14. 背景,要解决的问题
  15. 采用的代码设计模式
  16. 监控
  17. 性能(核心API)
  18. 边界:系统、代码、接口
  19. 拆出来提测文档
  20. 需求解析
  21. 逻辑结构:数据模型、时序模型、状态机模型;物理结构:DB;部署结构:依赖=>上线步骤
  22. 线上检查方法
  23. 事务:特例考虑分布式事务
  24. 数据处理方式:DB、Cache;一致性处理
  25. 并发处理:锁、幂等操作
  26. 发布考虑:监控、灰度、应急方案(回滚、降级)
  27. 技术选型:对比优缺点
  28. 数据模型
  29. 策略算法:需要画流程图
  30. 名词定义、术语
  31. 相关方、利益(收益)
  32. 问题:代码与设计不符
  33. 线上问题度量:线上执行SQL刷数据次数、JSP后门执行次数、蜂利器任务提报问题数量
  34. API类别:存储、对外、模块间
  35. API设计之前:先一句话描述

领域驱动设计在马蜂窝优惠中心重构中的实践

前言

正如领域驱动设计之父 Eric Evans 所著一书的书名所述,领域驱动设计(Domain Driven Design)是一种软件核心复杂性应对之道。

在我们解决现实业务问题时,会面对非常复杂的业务逻辑。即使是同一个事物,在多个子业务单元下代表的意思也是不完全一样的。比如「商品」这个词,在商品详情页语境中,是指「商品基本信息」;在下单页语境中,是指「购买项」;而在物流页面语境中,又变成了「被运送的货物」。

DDD 的核心思想就是让正确的领域模型发挥作用。所谓「术业有专攻」,DDD 指导软件开发人员将不同的子业务单元划分为不同的子领域,在各个子领域内部分别对事物进行建模,来应对业务的复杂性。

Part 1

重构优惠中心的背景

我们在实际的开发过程中都遇到过这种情况,最初因为业务逻辑比较单一,为了快速实现功能, 以及对成本、风险等因素的综合考虑,我们会为业务统一创建一个大的模型,各个模块都使用这同一个模型。但随着业务的发展,各子领域的逻辑越来越复杂,对这个大模型的修改就会变成一种灾难,有时明明是要改一个 A 子领域的逻辑,却莫名其妙影响到了 B 或者 C 子领域的线上功能。

优惠中心就是一个例子。优惠中心主要负责马蜂窝各业务线商品的优惠活动管理,以及计算不同用户的优惠结果。「商品管理」和「优惠管理」作为两个不同的业务单元,在初期被设计为共用一个商品模型,由商品模块统一管理。

图1 :初期商品模型

出现的问题

随着业务的发展,优惠的形式不断推陈出新,业务形态逐渐多样,业务方的需求也越来越个性化,导致后期的优惠中心无论从功能上还是系统上都出现了一些具体的问题:

1. 功能上来说,不够灵活

优惠信息是作为商品信息的一个属性在商品管理模块配置的。比如为了引导用户使用 App 需要设置 A 类型优惠,就通过在商品信息的编辑页面增加一个 A 类型优惠配置项实现;如果某个商品的 A 类型优惠需要在 0:00 分生效,业务同学就必须在电脑前等到 0:00 更新商品信息来上线优惠活动。

另外,如果想要创建针对所有商品都适用的优惠,按照之前的模式,所有的商品都要设置一遍,这几乎是不可接受的。

2. 从系统层面看,不易扩展

优惠信息存储在商品信息中,优惠信息是通过商品管理模块的接口输出的。如果要新增一种优惠类型,商品信息相关的表就要增加字段,商品的表会越来越大;如果要迭代一个优惠的逻辑,就有可能影响到商品管理模块的功能。

3. 不利于迭代

由于优惠信息仅仅作为商品的一个属性,没有自己的生命周期,所以很难去统计某一次设置的优惠的投入产出比,从而指导后续的功能优化。

重构优惠中心的预期

  • 系统层面上,要把优惠相关的业务逻辑独立出来,单独设计和实现;
  • 应用层面上,优惠中心会有自己的独立后台,负责管理优惠活动;也会有独立的优惠计算接口,负责 C 端用户使用优惠时的计算。

Part 2

为什么选择 DDD

避免贫血模型

基于传统的 MVC 架构开发功能的时候,Model 层本质上是一个 DAO 层,业务逻辑通常会封装在 Service 层,然后 Controller 通过调用 Service 层来完成对外的功能。这种模式下,数据和行为分别被割裂到了 Model 和 Service 两层。我们把这种只承载数据,但没有业务行为的 Model 称为「贫血模型」。

我们在和业务方了解需求的过程中,使用到的对象都是现实业务的映射,是行为和属性的综合体。需求确定好之后,我们开发的过程中,人为把行为和数据拆分成了两部分,做了一次转换。随着需求的迭代,人员的更迭,开发看到的代码和业务方的需求越来越对应不上,导致很多代码谁也不知道对应的是什么业务逻辑,这种现象被称为由贫血模型带来的「失忆症」,最终导致的是一个维护成本极高的大泥潭系统。

领域驱动设计的核心就是基于业务逻辑去建模,避免贫血模型,减少设计和开发过程中对业务信息的丢失和转换。在业务逻辑迭代的过程中,系统通过调整对应的业务模型就可以完成迭代。

Part 3

落地过程

关键点:业务逻辑抽象

要做到基于业务逻辑建模,就要合理地抽象。因为业务表象千差万别,产品经理和软件设计人员需要和业务专家深入交流,并且从离散的信息中抽象出业务内在的逻辑。

比如旅游业务售卖的商品和标品不同,有些优惠是不考虑人群的,比如使用优惠券,所有类型的库存都可以享受;但如 N 人 N 折这类优惠,成人价可以享受,儿童价和单房差就不可以。基于这个特点,我们对优惠中心的商品模型做了抽象,抽象出来「是否可以参与件数计算」和 「是否可以参与价格计算」两个通用属性。这样既实现了基于业务逻辑建模,又不会陷入业务逻辑千差万别的表象中。

3.1 战术设计

第一步:统一语言,提炼关键词

准确的语言对于产品、运营、开发等各方对齐需求非常重要,我们需要将优惠逻辑当中的概念抽象为各方都能理解的词语,以达成共识。作为开发人员来说,对领域的理解一般来说是比较少的,为了抽象出合理的语言让产品和业务方都能理解,就需要充分理解业务背景和需求。在熟悉业务和需求的过程中,提炼出若干关键字,这些关键词就是最初产生的领域概念和通用语言。比如:

  • 优惠类型:表示一种优惠规则和对应的优惠方案。比如早鸟优惠,就是早多少钱买(优惠规则),减多少钱/打几折(优惠方案);
  • 优惠活动:拥有完整的生命周期,需要包含时间、平台、人员、商品等(限制维度)的某种优惠类型的使用过程信息;
  • 优惠发现:根据指定的商品、人员和平台,找出可以使用的优惠活动列表服务;
  • 优惠计算:根据指定的商品、人员、平台以及购买数量,计算出这一次购买行为可以享受的优惠金额及优惠明细;
  • 优惠排序:各种优惠类型在计算的时候是有先后顺序的,如果有打折的优惠存在,那顺序不同,计算的结果也会不同;
  • 优惠互斥:某些优惠之间存在互斥的关系,比如使用了金卡 96 折优惠,就不能使用马蜂窝优惠券。

第二步:抽象领域模型

根据单一职责的原则,一个领域概念对应一个领域对象。领域对象有实体值对象之分:

  • 实体:实体是有状态的和唯一标识的,包含属性和行为;
  • 值对象:值对象是无状态的,是只读的,包含属性和行为。

区分实体和值对象对系统设计有很大意义,实体是我们需要重点关注和设计的,而值对象则只使用它的「值」就可以了。这样可以简化系统的复杂度,将精力聚焦在核心领域对象。不难理解,优惠活动毋庸置疑是一个实体,优惠类型就是一个值对象。

但也存在某些业务行为是不能归于某个实体或值对象的,可以将它们归为领域服务:

  • 领域服务:领域服务本质上就是一些操作,不包含状态,通常用于协调多个实体。实体和值都属于领域对象,领域对象之间的交互逻辑不能放在领域对象内部,必须由服务来实现,从而有效地保护领域模型。

有一些领域逻辑,比如「优惠排序」和「优惠互斥」,他们涉及到多个优惠类型,也就是多个领域对象。如果也被设计为领域对象,就打破了单一职责的原则,所以我们把这部分跨多个领域对象的业务逻辑放到「领域服务」层。

第三步:抽象领域对象之间的关联关系

将相关联的领域对象进行显式分组,来表达整体的概念(也可以是单一的领域对象),也就是「聚合」

比如优惠活动是优惠类型、优惠范围等的聚合;优惠类型是优惠规则和优惠方案的聚合;优惠规则是限制维度的聚合;优惠方案是优惠手段的聚合:

图2 :关联关系示意

聚合的主要功能是把领域对象分组,外部的唯一访问点就是聚合根,这样可以避免处理领域对象间的一一对应关系,只需要处理聚合和聚合之间的关系就行了。

第四步:走查场景,调整领域模型

领域模型的调整是贯穿整个设计和开发过程的,随着业务的调整,领域模型也需要调整。比如优惠中心后期引入了会员卡的优惠类型,那么就需要把优惠券这个优惠类型的显示,调整为与会员卡互斥的优惠券和与会员卡不互斥的两种。

第五步:简化设计,降低系统复杂度

建模的本质是对现实事物的一种简化和抽象,指导我们忽略和问题域无关的事实,提取和问题域息息相关的信息。以优惠中心为例,最初的方案里我们设计了优惠类型管理的功能,根据不同的优惠规则和优惠方案自动组合成不同类型的优惠类型。但是可以预见,未来的优惠类型是有限的,并且每个优惠类型都有会自己的特殊配置,比如 N 人优惠里的 每 N 人/第 N 人;早鸟中的提前 N 天等。也就是说,根据优惠规则和优惠方案自动生成优惠类型基本是没有使用场景的,因此也就去掉了这个设计。

再如,对优惠的限制我们最初是设计在优惠活动维度,经过权衡,为了降低系统复杂度,最后实现在了优惠类型层面。以「蜂抢」优惠类型为例,它的规则是所有的蜂抢活动都是 1 个用户只能抢一次,没有必要把这个限制放在优惠活动维度,在优惠类型层面控制就可以了。

3.2 战略设计

战略设计处理的是不同限界上下文之间的拆分和集成逻辑。限界上下文比较抽象,结合我们在文章开始提到的不同语境中的「商品」例子来理解,同一个词如果不说明白所处的语境,是无法准确描述清楚其表达的含义的。「语境」其实就是「上下文」,对应不同「子领语」。同理,如果不在一个限定好的上下文中去设计领域模型,设计出的领域模型是不清晰的,它就会同时支持多个上下文。

这里需要说明一点,如果是从零搭建一个全新的电商系统,首先需要做的应该是战略设计。而优惠中心是建立在现有大的电商系统基础上,相当于作为其中一个子领域进行重构,所以我们才会先来做战术设计,再考虑在完整的电商系统下它与外部其他环境之间的关系,也就是战略设计。

优惠中心内部场景区分

优惠中心包括了服务于 B 端用户的优惠活动管理和服务于 C 端用户的优惠计算这两个不同的子业务单元:

图3 :优惠中心内部场景区分

  • 优惠活动处理的是优惠活动的增删改查,以及配套的统计等业务;优惠活动在这里是一个实体,有完整的生命周期,有上线、下线等状态,可以被创建和删除;
  • 优惠计算处理的是一个订单能享受哪些优惠,并减多少钱的问题;在这个场景里,优惠活动是一个值对象,只提供优惠计算需要的必要参数即可。

优惠中心与外部系统集成

在整个电商系统的环境下,优惠中心作为一个子域,处于自己的限界上下文当中。使用优惠中心服务的详情页、下单页都处于自己各自的限界上下文,所以调用优惠中心的时候就需要设计它们之间的上下文映射方式。

调用和被调用方使用的战略设计方法通常有以下几种:

  • 客户方-供应方:适用于同一个团队之间的协作,上游会有严格的自动化测试,来保证给到下游的数据是一定符合约定的;
  • 遵奉者:适用于不同团队协作,且上游不关心下游的标准,下游又完全「逆来顺受」地接受了上游给的数据的场景;
  • 防腐层:适用于上游不关心下游的标准,但是下游不甘心「逆来顺受」,就增加一层,来做转换处理,保持下游系统的独立性;
  • 开放主机服务:适用于中台(通用能力平台),对接方非常多,业务重复度高,并且已经有完善的测试机制和通用的模型。

结合我们的实际情况来看,调用优惠中心的可能会是不同团队的开发人员,而优惠中心又不想被不同的上游侵入内部设计中,所以「客户方-供应方」和「遵奉者」模型都不适合;另外优惠中心前期接入方会比较少,而且会不断迭代,使用「开放主机服务」也不太合适。综合考虑下,防腐层的设计比较适合优惠中心。

下图是优惠中心的业务架构示意,中间的应用服务层采用的就是防腐层的设计,反映优惠中心与外部系统集成时的上下文映射关系:

图4 :优惠中心业务架构

3.3 架构实现

优惠中心选择的是经典的分层架构。从上到下为用户接口层、应用服务层、领域层和仓储层。图中不同的颜色块分别对映外部服务、应用服务、领域服务、聚合根、实体、值对象和仓储。

图5 :优惠中心分层领域模型

  • 用户接口层:处理和终端用户的交互逻辑;
  • 应用服务层:负责封装和转换领域层的返回数据给用户接口层;
  • 领域层:优惠中心的核心逻辑都在这一层,包括领域对象和领域服务。
  • 仓储层:仓储层负责把内存中的领域对象落地到存储介质,也负责从存储介质拿到原始数据后构造领域对象给领域层使用;这一层对领域层隐藏了底层的存储细节。虽然仓储层处在领域层下方,但是我们实现过程中采用了依赖注入的方式,将仓储层的具体实现注入到领域层中。

Part 4

问题及近期规划

1. 价格层优惠

现在公司面没有一个统一的商品中心,并且各业务线对商品的定义差别很大。比如自由行的商品包括出行日期、价格类别(成人价、儿童价)和套餐类别等层级;而火车票的商品包含座次、席别、目的地和出发地等层级。

如果优惠中心抽象出一种通用的商品层级来适配各个业务线,那实际上就是优惠中心要对商品进行标准定义,但是这个标准与后续商品中心的标准定义很有可能是不一致的,如果不一致优惠中心就要做大的改版。所以最终的解决方案可能还要通过推进统一商品中心的建立来解决。

2. 性能问题

领域驱动设计带来的弊端就是类的增多。目前优惠中心的技术栈基于 PHP, PHP 是一种解释型语言,在DDD 模式下即使有了 OPCode 等缓存技术,执行阶段的耗时相对其他静态数据类型的语言还是较大。所以后面计划将优惠中心使用 Java 技术栈重构,来进行性能上的优化。

Part 5

小结

本文介绍了马蜂窝电商优惠中心基于 DDD 进行重构的一些实践经验。DDD 的思想也帮助我们在业务迭代的过程中将架构设计得更加合理。

当然,是否采用业务驱动设计的思想,需要取决于业务和团队的实际情况。在马蜂窝业务的快速发展下,我们在架构设计上还将做更多的探索,也将持续与大家交流。