@Lenciel

如何写好系统架构文档

软件开发实际上是一个学习的过程,架构和代码只是它的副产品。

所以方案应该主要体现两个部分:

  1. 你对用户需求、关键路径等「领域知识」有了什么样的了解。
  2. 你因为这些了解,在:
  • 系统的核心模块准备采取什么样的设计
  • 模块之间通过什么方式通信或者暴露什么 API
  • 数据怎么进行读写和持久化

等关键选择上做了什么样的选择和权衡。

本文面向所有需要编写系统设计方案或者系统架构方案的工程师。

目录

一、基本步骤

1. 梳理和澄清系统

维基百科对「系统」的定义是:

A system is a group of interacting or interrelated entities that form a unified whole. A system, surrounded and influenced by its environment, is described by its boundaries, structure and purpose and expressed in its functioning.

因此,一个系统的定义主要有几个方面:

  • 目的
  • 边界
  • 模块(or 子系统)
  • 模块(or 子系统)间的协同关系

1.1 目的

系统的目的主要通过「用户故事」来表达。书写用户故事是产品经理的基本功,但同时,也是所有进行系统设计和分析的人的基本功。

用户故事的结构是三部分:

  • 角色(谁要使用,为谁而设计?)
  • 功能(这个功能有什么作用,怎么获得)
  • 价值(为什么用户需要这个功能)

在实际书写过程里面,「用户故事」可以是文本的,也可以是表格,甚至可以是用 UML 的用例图或者序列图。

以我们的镜子为例,下面是一个完整的用户故事:

「成都天府软件园的一家中型互联网公司,有300人的规模。这家公司的CEO大凡在“软件园CEO群”里面得知,FITURE魔镜开始给企业提供三个月试用,于是安排公司中的HR同事小凡来负责跟进。小凡根据大凡提供的联系方式,联系到了FITURE的BD,在提交了必要的公司证明材料后,预约了3台FITURE魔镜产品,并和行政的同事商议,决定将FITURE魔镜分别摆放在公司的两个茶水间和一个专门的小型会议室。

第二天,FITURE的BD带着安装人员上门安装调试,并且给小凡介绍了如何试用,以及试用期间的运营手段。第二周开始,小凡每周四下午3点都会组织大家一起做工间操,感兴趣的同事聚集在茶水间的魔镜前面,花15分钟的时间跟着岳岳老师进行肩颈放松与背部拉伸,有效缓解了工作疲劳。上午上班前、午休时、下班后,也有部分同事通过会议室的魔镜进行单人锻炼。甚至由于想用的人太多,还需要通过公司的会议预约系统提前进行预约。

在两个月后,FITURE的BD再次和小凡交流,小凡和CEO大凡商量后,决定正式付费使用FITURE魔镜产品,作为公司给员工提供的福利之一。而且,考虑到员工排队的情况,找了另外一间大的会议室,又新增了一台FITURE魔镜。」

1.2 边界

中文里系统的「边界」,有两个维度:scope 和 constraints。其中「scope」主要是通过用户故事来抽象得到的,所以梳理完用户故事之后,我们一般还需要梳理的「边界」是系统的 「contraints」,正是这些约束条件会决定系统的一些关键特性:

  • Performance Efficiency
  • Compatibility
  • Availability & Reliability
  • Security
  • Maintainability
  • Portability

由于类似于 CAP 约束的原因,一个系统只能支持我们列出的体系结构特征里面的几个。因为每个架构特性通常会成为其他架构特性的约束。例如,如果一个架构师想要提高安全性,它几乎肯定会对性能产生负面影响:应用程序必须执行更多的加解密等降低性能的活动。

一般来说,在早期最主要需要梳理的约束条件,一般是跟流量/数据相关的,比如系统承接的 rps/bps,数据一致性要求的等等,这些会决定系统设计的时候,对可靠性、可扩展性、弹性等系统特性的决定。

在我很喜欢的《Designing Data-Intensive Applications》里,它提到的应用系统主要追求的三个方面就直接没有「可用性」,而是:

  • Reliability
  • Scalability
  • Maintainability

我觉得这里的原因,主要是「可用」更多是用户纬度的一个感受(系统在运行的过程中有多少时间是可以被用户使用的)。它本身是以「可靠性」(系统在出故障的情况十分能够完成工作)和「可维护性」(系统进行定期维护和故障处理十分方便)等其他工程纬度的指标为基础的。

2. 顶层设计

经过第一步的梳理,第二步就是进行顶层设计。一个系统在最顶层基本都可以划分为:

  • 应用层(App、小程序、Web Application 等等形式)
  • 接入层(一般会有流量管理,比如 AG 的设计)
  • 拆分出来的服务(有时候用户、商品、交易等等服务会在业务较多的时候为了复用成为一个 platform service,也就是常常看到的所谓「平台」或者「中台」或者「公共服务」)
  • 数据存储/持久化层(一开始通常主从数据库加上基本的缓存就够了)

3. 核心组件设计

前面我们讲系统的定义时说过,系统是由模块组成,通过模块间的协作完成功能的。

模块之间怎么协作呢?一般通过消息或者 API 调用来进行。

所以模块的设计一般是几个方面:

  • 根据功能使用 OOD(面向对象设计)来设计模块
  • 设计模块 的数据库 schema
  • 设计模块的 API 或者消息

可以说,模块边界的划分,API 或者消息的设计、schema 的设计等等,是架构师能力的主要体现。

4. 考虑系统的瓶颈和如何扩展当前的设计

当前架构是不是有性能或者安全的方面的瓶颈?什么时候应该使用什么方法解决这些瓶颈?比如数据库会变慢,需要做主从库做读写分离?需要分库分表?需要加缓存体系?

一个好的方案,一定是对当前业务情况最适用,投入产出比最高的方案。这也往往意味着,这个方案代表的系统,多半会在一年左右大规模重构:因为一个健康的互联网业务一般一年流量就应该翻很多倍了

二、核心命题

方案需要体现对以下问题的思考:

  1. 系统的价值、构成、边界和约束条件
  2. 系统有哪些角色,关键用户路径的流程是什么,有怎样的 SLA/SLI/SLO
  3. 有什么样的假设,有什么样的依赖条件
  4. 如何保障可用性和可靠性的细节 a. 包括但不限于流量怎么切分 b. 缓存怎么设计 i. Application caching ii. Database caching iii. Object caching(KV存储如Reids或Memchache) iv. … c. 数据怎么放怎么取 d. 系统的弹性怎么保障
  5. 系统在安全性等方面的考虑
  6. 有什么外部依赖和风险

这里就不一一展开了。

2020年终总结

年底事儿挺多,《红楼梦》还没读完1

很多朋友也觉得今年过得特别快。

其实,以「年」计算的时间,对成年人来说通常都是在不知不觉中,一晃而过的。

反倒是一天,往往很漫长

再说,在这史蒂芬金编剧周星驰导演的一年里,很多人没有扛过去234

能够一晃而过,应该觉得幸运。

所以,艾师兄说,「活着,就够了」。

疫情给我最大的触动是,人的注意力其实是人拥有的最有流动性,最有价值的资产。

移动互联网时代,很多产品抓住人类的弱点来诱惑我们,把注意力作为商品来攫取。

但即使你像我一样,不装头条的产品5,不逛购物网站,不玩游戏,也扛不住疫情后,远程办公在线开会,各种通知提醒在各种工具里飞来飞去。

Aldous Huxley 在他的乌托邦小说《》里,描绘了一种名为「Mynahs」的鸟,它们周期性地飞来飞去,嘴里叨叨着「注意注意」,来帮助做白日梦的居民回到他们自己的现实生活中。

我们今天的问题是大家哪怕想要集中注意力,社会制度和结构也释放了太多「Mynahs」,迫使我们频繁快速地切换上下文,以至于没有人可以集中注意力。

要怎么守住注意力这项资产,不同的人大概是有很多不同办法的。

我好像找到了自己的办法,今年单位时间的产出略有提高。

一开始,我很羡慕那些可以把日程表维护得规规整整并且严格执行的人,认真研究和使用了很多时间管理的方法,发现对我来说都不太有用。

这可能有点像刚开始创业时,我总是想 工作生活怎么平衡,也研究了各种方式方法,然后放弃了

一路下来,我形成了一个观念:你如果在找「平衡」,这个多了,那个就少了,心理上就很容易进入博弈。

可以把工作看成生活的一部分。

投入地去工作也是一种美好的生活。

如果你需要 8 个小时睡眠,需要有假期去世界各地旅行,才能保持投入的工作,就去找这样的工作,但保证在工作时全力以赴6

寻求「平衡」比心理博弈更负面的影响是,你让自己陷入了一个「零和」的游戏。

认为做某件事情就影响了其他事情,这很「零和」。

对我来说,保持注意力的方式不是固执地对某些想要去做的事情说不,而是允许自己的注意力在某段时间里因为探索这些选择而非常「涣散」。

我从来没法靠日程表上的一个会议提醒,或者某个信念,在接下来的几十分钟里立刻变得专注。

人应该去打开自己觉得装着宝藏的门,然后对自己说,「好的,我满足了」,而不应该通过强迫自己选择一个选项来「集中」注意力。

我怀疑这是为什么国外老师或者学生有「gap year」,Google 早期有 20%的自由时间的原因。

如果你写程序的时候想着《红楼梦》,可能是因为你内心真的想要探索一下《红楼梦》。

不要管它,放手去干。

专注是目标,而不是实现路径。

没有人可以通过专注变得专注,只能通过遵从内心去探索,让每个探索都变得专注。

不要管,放手干。

做到不管,既靠觉悟,也靠积累;既是道理,也是功夫。

人总认为自己所思所想所为就是自己,那都是自己的一厢情愿。

还有的人认为自己看过的书讲过的道理就是自己,那就是前人所谓的「百年钻故纸」,这种人最不值得一提。

恰恰因为思想、情感、知识,它们不是你,它们自己有自己的运转,你才能得到它们,你才能使用它们。

你能做的就是不要让这些东西,打扰「真的」你。

  1. 不过我一直是《红楼梦》接受障碍症患者。读起来觉得没《查泰莱夫人的情人》透彻清楚,也没《金瓶梅》坦荡爽利。 

  2. 纪念马拉多纳 

  3. 纪念肖恩康纳利 

  4. 纪念胡萌 

  5. 但是我今天装上了飞书… 

  6. 所以我至今没有办法接受强制加班,因为这影响我全身心投入工作,不是美好的生活。