知识卡片

消息发送架构案例:用反属性分析避免过度设计

结构图卡

内容

一个消息发送应用(方案1)本来由主应用统一负责接收上游消息、调用下游终端发送、记录消息状态。当被要求支持高并发时,正向思维很容易直接想到引入消息队列中间件(MQ,方案2)。但如果用[[逆向思维的三种分类:反转型、转换型、缺点型|反转型逆向思维]],应该先从”高性能”的反属性(可能是请求响应时间慢)出发,分析方案1里到底是主应用自身、还是下游消息处理终端的性能限制导致了这个反属性——做完这层反属性分析,很可能根本不需要在方案2里引入MQ。方案2本身还存在明显缺陷(消息发送方与MQ耦合太紧、MQ消息丢失后数据库里查不到记录),于是不少架构师会在方案2基础上设计出方案3(用接收方解耦发送方和MQ,接收方在数据库登记消息以解决丢失问题,MQ还起到削峰填谷的作用)。但把方案3和最初的方案1对比会发现:方案3可能只是缓解了下游终端的性能瓶颈,并没有解决接收方自身和数据库本身的性能问题,同时又引入了接收方/MQ/消费方的高可用问题、消息响应从同步变异步、MQ消息丢失等新的复杂性,实现和维护成本比方案1大幅提升。这说明在正向思维的单向链路设计下很容易出现过度设计——只有叠加向后思考的逆向思维(反属性分析),才能看清当前阶段真正的痛点:如果是主应用自身原因,可以对应用做水平克隆;如果是主应用访问数据库的性能原因,可以扩容服务器节点或分库分表;如果是下游终端处理能力导致,可以优先用令牌桶或漏桶算法限流。可迁移启发:面对”要不要引入一个重量级中间件(MQ、缓存、消息总线)”这类决策时,先做一次反属性分析——搞清楚当前瓶颈到底卡在哪个具体环节,再判断这个瓶颈是不是真的需要一整套新中间件才能解决,还是靠水平扩容、限流这类更轻量的手段就能化解,避免把”正向思维默认方案”直接当成”唯一正确答案”。

结构图

flowchart TB
  P1["方案1:主应用统一收发+记录"]
  P1 -->|正向思维:默认引入MQ| P2["方案2:引入MQ(但耦合紧,消息可能丢失)"]
  P2 -->|继续修补| P3["方案3:接收方解耦+登记消息<br/>(新增高可用/异步/丢消息等复杂性,成本大增)"]
  P1 -->|逆向思维:先做反属性分析| Q["找到真正瓶颈:主应用自身?数据库?下游终端?"]
  Q --> S1["主应用瓶颈→水平克隆"]
  Q --> S2["数据库瓶颈→扩容/分库分表"]
  Q --> S3["下游终端瓶颈→令牌桶/漏桶限流"]

参考来源

- 位置:《架构师启示录:知识模型、落地方法与思维模式》第10章《底层思维模式》之"10.4.3 如何利用逆向思维完善架构设计"(消息发送场景,源文件:_epub-src/EPUB/xhtml/chapter14.xhtml) - 结论依据:原文说明"如果采用逆向思维,我们最先应该做的是从高性能的反属性(可能是请求响应时间慢)出发,去分析方案1中哪些因素导致了反属性的出现……如果进行了反属性的分析,那么很可能就不需要在方案2中引入MQ的方案了……通过引入逆向思维,叠加向后思考能让我们更加清楚当前所处阶段面临的真正痛点", 直接支撑本卡关于消息发送架构反属性分析案例的结构图。 - 原始内容:而且,相比方案1,方案3又引入了更多的复杂性,包括接收方、MQ、消费方的高可用问题,以及消息响应需要同步转为异步、MQ消息丢失等问题,实现和维护成本较方案1有了大幅度的提升。