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.

111 lines
8.5 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.

# 13 | 架构设计流程:详细方案设计
完成备选方案的设计和选择后我们终于可以长出一口气因为整个架构设计最难的一步已经完成了但整体方案尚未完成架构师还需继续努力。接下来我们需要再接再励将最终确定的备选方案进行细化使得备选方案变成一个可以落地的设计方案。所以今天我来讲讲架构设计流程第4步详细方案设计。
## 架构设计第4步详细方案设计
简单来说,详细方案设计就是将方案涉及的关键技术细节给确定下来。
* 假如我们确定使用Elasticsearch来做全文搜索那么就需要确定Elasticsearch的索引是按照业务划分还是一个大索引就可以了副本数量是2个、3个还是4个集群节点数量是3个还是6个等。
* 假如我们确定使用MySQL分库分表那么就需要确定哪些表要分库分表按照什么维度来分库分表分库分表后联合查询怎么处理等。
* 假如我们确定引入Nginx来做负载均衡那么Nginx的主备怎么做Nginx的负载均衡策略用哪个权重分配轮询ip\_hash等。
可以看到详细设计方案里面其实也有一些技术点和备选方案类似。例如Nginx的负载均衡策略备选有轮询、权重分配、ip\_hash、fair、url\_hash五个具体选哪个呢看起来和备选方案阶段面临的问题类似但实际上这里的技术方案选择是**很轻量级的**,我们无须像备选方案阶段那样操作,而只需要简单根据这些技术的适用场景选择就可以了。
例如Nginx的负载均衡策略简单按照下面的规则选择就可以了。
* 轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器后端服务器分配的请求数基本一致如果后端服务器“down掉”能自动剔除。
* 加权轮询
根据权重来进行轮询,权重高的服务器分配的请求更多,主要适应于后端服务器性能不均的情况,如新老服务器混用。
* ip\_hash
每个请求按访问IP的hash结果分配这样每个访客固定访问一个后端服务器主要用于解决session的问题如购物车类的应用。
* fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配,能够最大化地平衡各后端服务器的压力,可以适用于后端服务器性能不均衡的情况,也可以防止某台后端服务器性能不足的情况下还继续接收同样多的请求从而造成雪崩效应。
* url\_hash
按访问URL的hash结果来分配请求每个URL定向到同一个后端服务器适用于后端服务器能够将URL的响应结果缓存的情况。
这几个策略的适用场景区别还是比较明显的根据我们的业务需要挑选一个合适的即可。例如比如一个电商架构由于和session比较强相关因此如果用Nginx来做集群负载均衡那么选择ip\_hash策略是比较合适的。
**详细设计方案阶段可能遇到的一种极端情况就是在详细设计阶段发现备选方案不可行,一般情况下主要的原因是备选方案设计时遗漏了某个关键技术点或者关键的质量属性。**例如我曾经参与过一个项目在备选方案阶段确定是可行的但在详细方案设计阶段发现由于细节点太多方案非常庞大整个项目可能要开发长达1年时间最后只得废弃原来的备选方案重新调整项目目标、计划和方案。这个项目的主要失误就是在备选方案评估时忽略了开发周期这个质量属性。
幸运的是,这种情况可以通过下面方式有效地避免:
* **架构师不但要进行备选方案设计和选型,还需要对备选方案的关键细节有较深入的理解。**例如架构师选择了Elasticsearch作为全文搜索解决方案前提必须是架构师自己对Elasticsearch的设计原理有深入的理解比如索引、副本、集群等技术点而不能道听途说Elasticsearch很牛所以选择它更不能成为把“细节我们不讨论”这句话挂在嘴边的“PPT架构师”。
* **通过分步骤、分阶段、分系统等方式,尽量降低方案复杂度**,方案本身的复杂度越高,某个细节推翻整个方案的可能性就越高,适当降低复杂性,可以减少这种风险。
* 如果方案本身就很复杂,那就采取**设计团队**的方式来进行设计博采众长汇集大家的智慧和经验防止只有1~2个架构师可能出现的思维盲点或者经验盲区。
## 详细方案设计实战
虽然我们上期在“前浪微博”消息队列的架构设计挑选了备选方案2作为最终方案但备选方案设计阶段的方案粒度还比较粗无法真正指导开发人员进行后续的设计和开发因此需要在备选方案的基础上进一步细化。
下面我列出一些备选方案2典型的需要细化的点供参考有兴趣的同学可以自己尝试细化更多的设计点。
1.细化设计点1数据库表如何设计
* 数据库设计两类表一类是日志表用于消息写入时快速存储到MySQL中另一类是消息表每个消息队列一张表。
* 业务系统发布消息时,首先写入到日志表,日志表写入成功就代表消息写入成功;后台线程再从日志表中读取消息写入记录,将消息内容写入到消息表中。
* 业务系统读取消息时,从消息表中读取。
* 日志表表名为MQ\_LOG包含的字段日志ID、发布者信息、发布时间、队列名称、消息内容。
* 消息表表名就是队列名称包含的字段消息ID递增生成、消息内容、消息发布时间、消息发布者。
* 日志表需要及时清除已经写入消息表的日志数据消息表最多保存30天的消息数据。
2.细化设计点2数据如何复制
直接采用MySQL主从复制即可只复制消息存储表不复制日志表。
3.细化设计点3主备服务器如何倒换
采用ZooKeeper来做主备决策主备服务器都连接到ZooKeeper建立自己的节点主服务器的路径规则为“/MQ/server/分区编号/master”备机为“/MQ/server/分区编号/slave”节点类型为EPHEMERAL。
备机监听主机的节点消息,当发现主服务器节点断连后,备服务器修改自己的状态,对外提供消息读取服务。
4.细化设计点4业务服务器如何写入消息
* 消息队列系统设计两个角色:生产者和消费者,每个角色都有唯一的名称。
* 消息队列系统提供SDK供各业务系统调用SDK从配置中读取所有消息队列系统的服务器信息SDK采取轮询算法发起消息写入请求给主服务器。如果某个主服务器无响应或者返回错误SDK将发起请求发送到下一台服务器。
5.细化设计点5业务服务器如何读取消息
* 消息队列系统提供SDK供各业务系统调用SDK从配置中读取所有消息队列系统的服务器信息轮流向所有服务器发起消息读取请求。
* 消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读取的消息给消费者。
6.细化设计点6业务服务器和消息队列服务器之间的通信协议如何设计
考虑到消息队列系统后续可能会对接多种不同编程语言编写的系统为了提升兼容性传输协议用TCP数据格式为ProtocolBuffer。
当然还有更多设计细节就不再一一列举,因此这还不是一个完整的设计方案,我希望可以通过这些具体实例来说明细化方案具体如何去做。
## 小结
今天我为你讲了架构设计流程的第四个步骤:详细方案设计,并且基于模拟的“前浪微博”消息队列系统,给出了具体的详细设计示例,希望对你有所帮助。这个示例并不完整,有兴趣的同学可以自己再详细思考一下还有哪些细节可以继续完善。
这就是今天的全部内容留一道思考题给你吧你见过“PPT架构师”么他们一般都具备什么特点
欢迎你把答案写到留言区,和我一起讨论。相信经过深度思考的回答,也会让你对知识的理解更加深刻。(编辑乱入:精彩的留言有机会获得丰厚福利哦!)