You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
13 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 50 | 架构实战:架构设计文档模板
在前面的专栏里,有同学留言说想看看具体的架构设计文档。由于信息安全的原因,再加上稍微复杂的系统,设计文档都是几十页,因此专栏无法直接给出详细的文档案例。但我认为提供一个架构设计文档模板还是很有必要的,可以方便你在实际进行架构设计的时候更好地编写相关文档。我还以前面讲过的“前浪微博”消息队列为例,给出架构设计中最重要的两个文档的模板和关键说明。这个案例文档仅给出一些关键内容供你参考,部分细节无法全面覆盖或者完全保证正确。
## 备选方案模板
1.需求介绍
\[需求介绍主要描述需求的背景、目标、范围等\]
随着前浪微博业务的不断发展,业务上拆分的子系统越来越多,目前系统间的调用都是同步调用,由此带来几个明显的系统问题:
* 性能问题当用户发布了一条微博后微博发布子系统需要同步调用“统计子系统”“审核子系统”“奖励子系统”等共8个子系统性能很低。
* 耦合问题:当新增一个子系统时,例如如果要增加“广告子系统”,那么广告子系统需要开发新的接口给微博发布子系统调用。
* 效率问题:每个子系统提供的接口参数和实现都有一些细微的差别,导致每次都需要重新设计接口和联调接口,开发团队和测试团队花费了许多重复工作量。
基于以上背景,我们需要引入消息队列进行系统解耦,将目前的同步调用改为异步通知。
2.需求分析
\[需求分析主要全方位地描述需求相关的信息\]
**5W**
\[5W指Who、When、What、Why、Where。
Who需求利益干系人包括开发者、使用者、购买者、决策者等。
When需求使用时间包括季节、时间、里程碑等。
What需求的产出是什么包括系统、数据、文件、开发库、平台等。
Where需求的应用场景包括国家、地点、环境等例如测试平台只会在测试环境使用。
Why需求需要解决的问题通常和需求背景相关\]
消息队列的5W分析如下
Who消息队列系统主要是业务子系统来使用子系统发送消息或者接收消息。
When当子系统需要发送异步通知的时候需要使用消息队列系统。
What需要开发消息队列系统。
Where开发环境、测试环境、生产环境都需要部署。
Why消息队列系统将子系统解耦将同步调用改为异步通知。
**1H**
\[这里的How不是设计方案也不是架构方案而是关键业务流程。消息队列系统这部分内容很简单但有的业务系统1H就是具体的用例了有兴趣的同学可以尝试写写ATM机取款的业务流程。如果是复杂的业务系统这部分也可以独立成“用例文档”\]
消息队列有两大核心功能:
* 业务子系统发送消息给消息队列。
* 业务子系统从消息队列获取消息。
**8C**
\[8C指的是8个约束和限制即Constraints包括性能Performance、成本Cost、时间Time、可靠性Reliability、安全性Security、合规性Compliance、技术性Technology、兼容性Compatibility\]
注:需求中涉及的性能、成本、可靠性等仅仅是利益关联方提出的诉求,不一定准确;如果经过分析有的约束没有必要,或成本太高、难度太大,这些约束是可以调整的。
性能需要达到Kafka的性能水平。
成本参考XX公司的设计方案不超过10台服务器。
时间期望3个月内上线第一个版本在两个业务尝试使用。
可靠性按照业务的要求消息队列系统的可靠性需要达到99.99%。
安全性:消息队列系统仅在生产环境内网使用,无需考虑网络安全;如消息中有敏感信息,消息发送方需要自行进行加密,消息队列系统本身不考虑通用的加密。
合规性消息队列系统需要按照公司目前的DevOps规范进行开发。
技术性目前团队主要研发人员是Java最好用Java开发。
兼容性:之前没有类似系统,无需考虑兼容性。
3.复杂度分析
\[分析需求的复杂度,复杂度常见的有高可用、高性能、可扩展等,具体分析方法请参考专栏前面的内容\]
注:文档的内容省略了分析过程,实际操作的时候每个约束和限制都要有详细的逻辑推导,避免完全拍脑袋式决策,具体请参考[专栏第10期](http://time.geekbang.org/column/article/7563)的分析。
**高可用**
对于微博子系统来说如果消息丢了导致没有审核然后触犯了国家法律法规则是非常严重的事情对于等级子系统来说如果用户达到相应等级后系统没有给他奖品和专属服务则VIP用户会很不满意导致用户流失从而损失收入虽然也比较关键但没有审核子系统丢消息那么严重。
综合来看,消息队列需要高可用性,包括消息写入、消息存储、消息读取都需要保证高可用性。
**高性能**
前浪微博系统用户每天发送1000万条微博那么微博子系统一天会产生1000万条消息平均一条消息有10个子系统读取那么其他子系统读取的消息大约是1亿次。将数据按照秒来计算一天内平均每秒写入消息数为115条每秒读取的消息数是1150条再考虑系统的读写并不是完全平均的设计的目标应该以峰值来计算。峰值一般取平均值的3倍那么消息队列系统的TPS是345QPS是3450考虑一定的性能余量。由于现在的基数较低为了预留一定的系统容量应对后续业务的发展我们将设计目标设定为峰值的4倍因此最终的性能要求是TPS为1380QPS为13800。TPS为1380并不高但QPS为13800已经比较高了因此高性能读取是复杂度之一。
**可扩展**
消息队列的功能很明确,基本无须扩展,因此可扩展性不是这个消息队列的关键复杂度。
4.备选方案
\[备选方案设计至少3个备选方案每个备选方案需要描述关键的实现无须描述具体的实现细节。此处省略具体方案描述详细请参考[专栏第11期](http://time.geekbang.org/column/article/7800)\]
**备选方案1直接引入开源Kafka**
\[此处省略方案描述\]
**备选方案2集群 + MySQL存储**
\[此处省略方案描述\]
**备选方案3集群 + 自研存储**
\[此处省略方案描述\]
5.备选方案评估
\[备选方案360度环评详细请参考[专栏第12期](http://time.geekbang.org/column/article/7832)。注意备选方案评估的内容会根据评估会议的结果进行修改,也就是说架构师首先给出自己的备选方案评估,然后举行备选方案评估会议,再根据会议结论修改备选方案文档\]
## 架构设计模板
\[备选方案评估后会选择一个方案落地实施,架构设计文档就是用来详细描述细化方案的\]
1.总体方案
\[总体方案需要从整体上描述方案的结构,其核心内容就是架构图,以及针对架构图的描述,包括模块或者子系统的职责描述、核心流程\]
2.架构总览
\[架构总览给出架构图以及架构的描述\]
![](https://static001.geekbang.org/resource/image/4f/7f/4f1d5422c5967c6be42c6d2d8d34127f.jpg)
架构关键设计点:
* 采用数据分散集群的架构,集群中的服务器进行分组,每个分组存储一部分消息数据。
* 每个分组包含一台主MySQL和一台备MySQL分组内主备数据复制分组间数据不同步。
* 正常情况下,分组内的主服务器对外提供消息写入和消息读取服务,备服务器不对外提供服务;主服务器宕机的情况下,备服务器对外提供消息读取的服务。
* 客户端采取轮询的策略写入和读取消息。
3.核心流程
* 消息发送流程
\[此处省略流程描述\]
* 消息读取流程
\[此处省略流程描述\]
4.详细设计
\[详细设计需要描述具体的实现细节\]
**高可用设计**
* 消息发送可靠性
业务服务器中嵌入消息队列系统提供的SDKSDK支持轮询发送消息当某个分组的主服务器无法发送消息时SDK挑选下一个分组主服务器重发消息依次尝试所有主服务器直到发送成功如果全部主服务器都无法发送SDK可以缓存消息也可以直接丢弃消息具体策略可以在启动SDK的时候通过配置指定。
如果SDK缓存了一些消息未发送此时恰好业务服务器又重启则所有缓存的消息将永久丢失这种情况SDK不做处理业务方需要针对某些非常关键的消息自己实现永久存储的功能。
* 消息存储可靠性
消息存储在MySQL中每个分组有一主一备两台MySQL服务器MySQL服务器之间复制消息以保证消息存储高可用。如果主备间出现复制延迟恰好此时MySQL主服务器宕机导致数据无法恢复则部分消息会永久丢失这种情况不做针对性设计DBA需要对主备间的复制延迟进行监控当复制延迟超过30秒的时候需要及时告警并进行处理。
* 消息读取可靠性
每个分组有一主一备两台服务器,主服务器支持发送和读取消息,备服务器只支持读取消息,当主服务器正常的时候备服务器不对外提供服务,只有备服务器判断主服务器故障的时候才对外提供消息读取服务。
主备服务器的角色和分组信息通过配置指定通过ZooKeeper进行状态判断和决策。主备服务器启动的时候分别连接到ZooKeeper在/MQ/Server/\[group\]目录下建立EPHEMERAL节点假设分组名称为group1则主服务器节点为/MQ/Server/group1/master备服务器的节点为/MQ/Server/group1/slave。节点的超时时间可以配置默认为10秒。
**高性能设计**
\[此处省略具体设计\]
**可扩展设计**
\[此处省略具体设计。如果方案不涉及,可以简单写上“无”,表示设计者有考虑但不需要设计;否则如果完全不写的话,方案评审的时候可能会被认为是遗漏了设计点\]
**安全设计**
消息队列系统需要提供权限控制功能,权限控制包括两部分:身份识别和队列权限控制。
* 身份识别
消息队列系统给业务子系统分配身份标识和接入keySDK首先需要建立连接并进行身份校验消息队列服务器会中断校验不通过的连接。因此任何业务子系统如果想接入消息队列系统都必须首先申请身份标识和接入key通过这种方式来防止恶意系统任意接入。
* 队列权限
某些队列信息可能比较敏感,只允许部分子系统发送或者读取,消息队列系统将队列权限保存在配置文件中,当收到发送或者读取消息的请求时,首先需要根据业务子系统的身份标识以及配置的权限信息来判断业务子系统是否有权限,如果没有权限则拒绝服务。
**其他设计**
\[其他设计包括上述以外的其他设计考虑点,例如指定开发语言、符合公司的某些标准等,如果篇幅较长,也可以独立进行描述\]
* 消息队列系统需要接入公司已有的运维平台,通过运维平台发布和部署。
* 消息队列系统需要输出日志给公司已有的监控平台,通过监控平台监控消息队列系统的健康状态,包括发送消息的数量、发送消息的大小、积压消息的数量等,详细监控指标在后续设计方案中列出。
**部署方案**
\[部署方案主要包括硬件要求、服务器部署方式、组网方式等\]
消息队列系统的服务器和数据库服务器采取混布的方式部署一台服务器上部署同一分组的主服务器和主MySQL或者备服务器和备MySQL。因为消息队列服务器主要是CPU密集型而MySQL是磁盘密集型的所以两者混布互相影响的几率不大。
硬件的基本要求32核48G内存512G SSD硬盘考虑到消息队列系统动态扩容的需求不高且对性能要求较高因此需要使用物理服务器不采用虚拟机。
5.架构演进规划
\[通常情况下,规划和设计的需求比较完善,但如果一次性全部做完,项目周期可能会很长,因此可以采取分阶段实施,即:第一期做什么、第二期做什么,以此类推\]
整个消息队列系统分三期实现:
第一期实现消息发送、权限控制功能预计时间3个月。
第二期实现消息读取功能预计时间1个月。
第三期实现主备基于ZooKeeper切换的功能预计时间2周。