架构实践方法

一、识别复杂度

将主要的复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序,优先解决当前面临的最主要的复杂度问题。对于按照复杂度优先级解决的方式,存在一个普遍的担忧:如果按照优先级来解决复杂度,可能会出现解决了优先级排在前面的复杂度后,解决后续复杂度的方案需要将已经落地的方案推倒重来。这个担忧理论上是可能的,但现实中几乎是不可能出现的,原因在于软件系统的可塑性和易变性。对于同一个复杂度问题,软件系统的方案可以有多个,总是可以挑出综合来看性价比最高的方案。

二、设计备选方案

架构师的工作并不神秘,成熟的架构师需要对已经存在的技术非常熟悉,对已经经过验证的架构模式烂熟于心,然后根据自己对业务的理解,挑选合适的架构模式进行组合,再对组合后的方案进行修改和调整。

新技术都是在现有技术的基础上发展起来的,现有技术又来源于先前的技术。将技术进行功能性分组,可以大大简化设计过程,这是技术“模块化”的首要原因。技术的“组合”和“递归”特征,将彻底改变我们对技术本质的认识。

1.第一种常见的错误:设计最优秀的方案。
根据架构设计原则中“合适原则”和“简单原则“的要求,挑选合适自己业务、团队、技术能力的方案才是好方案;否则要么浪费大量资源开发了无用的系统(例如,之前提过的“亿级用户平台”的案例,设计了 TPS 50000 的系统,实际 TPS 只有 500),要么根本无法实现(例如,10 个人的团队要开发现在的整个淘宝系统)。

2.第二种常见的错误:只做一个方案。
这样做有很多弊端:

心里评估过于简单,可能没有想得全面,只是因为某一个缺点就把某个方案给否决了,而实际上没有哪个方案是完美的,某个地方有缺点的方案可能是综合来看最好的方案。

架构师再怎么牛,经验知识和技能也有局限,有可能某个评估的标准或者经验是不正确的,或者是老的经验不适合新的情况,甚至有的评估标准是架构师自己原来就理解错了。

单一方案设计会出现过度辩护的情况,即架构评审时,针对方案存在的问题和疑问,架构师会竭尽全力去为自己的设计进行辩护,经验不足的设计人员可能会强词夺理。

因此,架构师需要设计多个备选方案,但方案的数量可以说是无穷无尽的,架构师也不可能穷举所有方案,那合理的做法应该是什么样的呢?

备选方案的数量以 3 ~ 5 个为最佳。少于 3 个方案可能是因为思维狭隘,考虑不周全;多于 5 个则需要耗费大量的精力和时间,并且方案之间的差别可能不明显。

备选方案的差异要比较明显。例如,主备方案和集群方案差异就很明显,或者同样是主备方案,用 ZooKeeper 做主备决策和用 Keepalived 做主备决策的差异也很明显。但是都用 ZooKeeper 做主备决策,一个检测周期是 1 分钟,一个检测周期是 5 分钟,这就不是架构上的差异,而是细节上的差异了,不适合做成两个方案。

备选方案的技术不要只局限于已经熟悉的技术。设计架构时,架构师需要将视野放宽,考虑更多可能性。很多架构师或者设计师积累了一些成功的经验,出于快速完成任务和降低风险的目的,可能自觉或者不自觉地倾向于使用自己已经熟悉的技术,对于新的技术有一种不放心的感觉。就像那句俗语说的:“如果你手里有一把锤子,所有的问题在你看来都是钉子”。例如,架构师对 MySQL 很熟悉,因此不管什么存储都基于 MySQL 去设计方案,系统性能不够了,首先考虑的就是 MySQL 分库分表,而事实上也许引入一个 Memcache 缓存就能够解决问题。

3.第三种常见的错误:备选方案过于详细。
有的架构师或者设计师在写备选方案时,错误地将备选方案等同于最终的方案,每个备选方案都写得很细。这样做的弊端显而易见:

耗费了大量的时间和精力。

将注意力集中到细节中,忽略了整体的技术设计,导致备选方案数量不够或者差异不大。

评审的时候其他人会被很多细节给绕进去,评审效果很差。例如,评审的时候针对某个定时器应该是 1 分钟还是 30 秒,争论得不可开交。

正确的做法是备选阶段关注的是技术选型,而不是技术细节,技术选型的差异要比较明显。例如,采用 ZooKeeper 和 Keepalived 两种不同的技术来实现主备,差异就很大;而同样都采用 ZooKeeper,一个方案的节点设计是 /service/node/master,另一个方案的节点设计是 /company/service/master,这两个方案并无明显差异,无须在备选方案设计阶段作为两个不同的备选方案,至于节点路径究竟如何设计,只要在最终的方案中挑选一个进行细化即可。

三、评估和选择备选方案

上在完成备选方案设计后,如何挑选出最终的方案也是一个很大的挑战,主要原因有:

每个方案都是可行的,如果方案不可行就根本不应该作为备选方案。

没有哪个方案是完美的。例如,A 方案有性能的缺点,B 方案有成本的缺点,C 方案有新技术不成熟的风险。

评价标准主观性比较强,比如设计师说 A 方案比 B 方案复杂,但另外一个设计师可能会认为差不多,因为比较难将“复杂”一词进行量化

正因为选择备选方案存在这些困难,所以实践中很多设计师或者架构师就采取了下面几种错误的指导思想:

最简派:设计师挑选一个看起来最简单的方案。例如,我们要做全文搜索功能,方案 1 基于 MySQL,方案 2 基于 Elasticsearch。MySQL 的查询功能比较简单,而 Elasticsearch 的倒排索引设计要复杂得多,写入数据到 Elasticsearch,要设计 Elasticsearch 的索引,要设计 Elasticsearch 的分布式……全套下来复杂度很高,所以干脆就挑选 MySQL 来做吧。

最牛派:最牛派的做法和最简派正好相反,设计师会倾向于挑选技术上看起来最牛的方案。例如,性能最高的、可用性最好的、功能最强大的,或者淘宝用的、微信开源的、Google 出品的等。

最熟派:设计师基于自己的过往经验,挑选自己最熟悉的方案。我以编程语言为例,假如设计师曾经是一个 C++ 经验丰富的开发人员,现在要设计一个运维管理系统,由于对 Python 或者 Ruby on Rails 不熟悉,因此继续选择 C++ 来做运维管理系统。

领导派:领导派就更加聪明了,列出备选方案,设计师自己拿捏不定,然后就让领导来定夺,反正最后方案选的对那是领导厉害,方案选的不对怎么办?那也是领导“背锅”。

正确的做法是:列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。

常见的方案质量属性点有:性能、可用性、硬件成本、项目投入、复杂度、安全性、可扩展性等。在评估这些质量属性时,需要遵循架构设计原则 1“合适原则”和原则 2“简单原则”,避免贪大求全,基本上某个质量属性能够满足一定时期内业务发展就可以了。

按优先级选择,即架构师综合当前的业务发展情况、团队人员规模和技能、业务发展预测等因素,将质量属性按照优先级排序,首先挑选满足第一优先级的,如果方案都满足,那就再看第二优先级……以此类推。那会不会出现两个或者多个方案,每个质量属性的优缺点都一样的情况呢?理论上是可能的,但实际上是不可能的。在做备选方案设计时,不同的备选方案之间的差异要比较明显,差异明显的备选方案不可能所有的优缺点都是一样的。如:

架构师经过思考后,给出了最终选择备选方案 2,原因有:

排除备选方案 1 的主要原因是可运维性,因为再成熟的系统,上线后都可能出问题,如果出问题无法快速解决,则无法满足业务的需求;并且 Kafka 的主要设计目标是高性能日志传输,而我们的消息队列设计的主要目标是业务消息的可靠传输。

排除备选方案 3 的主要原因是复杂度,目前团队技术实力和人员规模(总共 6 人,还有其他中间件系统需要开发和维护)无法支撑自研存储系统(参考架构设计原则 2:简单原则)。

备选方案 2 的优点就是复杂度不高,也可以很好地融入现有运维体系,可靠性也有保障。

针对备选方案 2 的缺点,架构师解释是:

备选方案 2 的第一个缺点是性能,业务目前需要的性能并不是非常高,方案 2 能够满足,即使后面性能需求增加,方案 2 的数据分组方案也能够平行扩展进行支撑(参考架构设计原则 3:演化原则)。

备选方案 2 的第二个缺点是成本,一个分组就需要 4 台机器,支撑目前的业务需求可能需要 12 台服务器,但实际上备机(包括服务器和数据库)主要用作备份,可以和其他系统并行部署在同一台机器上。

备选方案 2 的第三个缺点是技术上看起来并不很优越,但我们的设计目的不是为了证明自己(参考架构设计原则 1:合适原则),而是更快更好地满足业务需求。

四、详细方案设计

详细设计方案阶段可能遇到的一种极端情况就是在详细设计阶段发现备选方案不可行,一般情况下主要的原因是备选方案设计时遗漏了某个关键技术点或者关键的质量属性。这种情况可以通过下面方式有效地避免:

架构师不但要进行备选方案设计和选型,还需要对备选方案的关键细节有较深入的理解。例如,架构师选择了 Elasticsearch 作为全文搜索解决方案,前提必须是架构师自己对 Elasticsearch 的设计原理有深入的理解,比如索引、副本、集群等技术点;而不能道听途说 Elasticsearch 很牛,所以选择它,更不能成为把“细节我们不讨论”这句话挂在嘴边的“PPT 架构师”。

通过分步骤、分阶段、分系统等方式,尽量降低方案复杂度,方案本身的复杂度越高,某个细节推翻整个方案的可能性就越高,适当降低复杂性,可以减少这种风险。

如果方案本身就很复杂,那就采取设计团队的方式来进行设计,博采众长,汇集大家的智慧和经验,防止只有 1~2 个架构师可能出现的思维盲点或者经验盲区。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/63078.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

80. 删除有序数组中的重复项 II

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 解题思路:因为数组有序,相等的元素一定相邻,所以可以使用一个变量num统计相等元素的个数,如果当前元素和前一个元素相等&#xff0c…

Linux系统上多文件C程序的编译与调试

一、先建立一个头文件add.h 通过vi创建一个add.h,并进行编写该文件,用来存放求和函数add()的声明: 二、建立一个add.c文件 通过vi创建一个add.c文件,并进行编写,用来存放求和函数add()的实现: 三、建立一…

【Github】SourceTree技巧汇总

sourceTree登录github账户 会跳转到浏览器端 按照Git Flow 初始化仓库分支 克隆远程仓库到本地 推送变更到远程仓库 合并分支 可以看到目前的本地分支(main、iOS_JS)和远程分支(origin/main、origin/HEAD、origin/iOS_JS)目前所处…

Vue.js2+Cesium1.103.0 七、Primitive 绘制航线元素

Vue.js2Cesium1.103.0 七、Primitive 绘制航线元素 用 Primitive 绘制航线元素,包括航点图标,航线线段,线段距离标注,航点序号,海拔标注,总航程等信息。 可同时绘制多条航线;可根据 id 清除指…

如何在CSS中水平居中一个元素?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用 margin: 0 auto⭐ 使用 Flexbox 布局⭐ 使用绝对定位和负边距⭐ 使用表格布局⭐ 使用网格布局⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅…

pytest-xdist分布式测试原理浅析

目录 pytest-xdist执行流程: pytest-xdist 模块结构: pytest-xdist分布式测试原理: pytest-xdist源码浅读: pytest-xdist执行流程: 解析命令行参数:pytest-xdist 会解析命令行参数,获取用户…

今天我花了一个通宵的时间安装Windows11系统居然失败,忍不住哭了!

🚀 个人主页 极客小俊 ✍🏻 作者简介:web开发者、设计师、技术分享博主 🐋 希望大家多多支持一下, 我们一起进步!😄 🏅 如果文章对你有帮助的话,欢迎评论 💬点赞&#x1…

WPS的excel表格单元格拖动数字日期等 不自增原因

对着表格中的每个单元格右下角,在变成下图,黑十字后,拖动这个十字.就会在右侧出现一个小窗口. 里面菜单中可以选择按序数增加 但是,如果拖动,发现小窗口菜单不出现.说明这一栏开启了筛选功能.清空筛选条件后,即可恢复自增功能.

Transformer(一)简述(注意力机制,NLP,CV通用模型)

目录 1.Encoder 1.1简单理解Attention 1.2.什么是self-attention 1.3.怎么计算self-attention 1.4.multi-headed(q,k,v不区分大小写) 1.5.位置信息表达 2.Decoder(待补充) 3.BERT 参考文献 1.Encode…

Python小白入门:文件、异常处理和json格式存储数据

这里写自定义目录标题 所用资料 一、从文件中读取数据1.1 读取整个文件1.2 文件路径1.3 逐行读取1.4 创建一个包含文件各行内容的列表1.5 使用文件的内容1.6 包含一百万位的大型文件1.7 圆周率值中包含你的生日吗练习题 二、写入文件2.1 写入空文件2.2 写入多行2.3 附加到文件练…

8.10 算法刷题【1道题】

8.10 算法刷题 22. 链表中环的入口结点(快慢指针) 22. 链表中环的入口结点(快慢指针) 原题链接 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x…

kube-prometheus 使用 blackbox-exporter 进行icmp 监控

安装kube-prometheus 后默认在monitoring namespace中有创建 blackbox-exporter deployment。但默认没有icmp的module配置,无法执行ping探测。因为即使有icmp module,默认配置也是无法执行ping探测的(这篇文章要解决的就是这个问题&#xff0…