简介
借助如何学习分布式系统 得来的经验,当一个知识足够复杂,如何学习它本身就很值得玩味
架构类资料
到目前为止,笔者关于架构的几篇文章或笔记
按照许式伟的说法,架构相关的图书大概有几类
- 架构思维类。 通常从一些著名的架构理论讲起,比如开闭原则、单一职责原则等等。其弊端在于过度理论化,而计算机科学归根到底属于工程技术类,应该实践第一。
- 设计模式类。 这类一般上来就进入架构的局部细节,每个模式的来龙去脉并不容易理解。就算理解了某个具体的模式,也很难真正做到活学活用。
- 分布式系统架构设计类。 通常从服务端的通用问题如一致性、高可用、高并发挑战等话题讲起,阐述大型业务系统面临的挑战。这些知识虽然非常有价值,但无法延伸至通用业务架构,对大部分企业的架构实践不具备真正的指导意义。
- 重构类。 主要讲如何如何改进代码,其实是最实用的一类。但在我看来,一个模块最初的地基是最重要的,基本决定了这座大厦能够撑多久,而重构更多侧重于大厦建成之后,在服务于人的前提下怎么去修修补补,延长生命。
也有人主张:最好的软件设计是简单易懂的设计,软件架构被高估,清晰简单的设计被低估
- 拉过来一名同事,在白板上写下你的设计方法。写出你在做什么,为什么要这么做,征求他们的意见
- 设计两种方案,并进行对比。大多数人在设计架构时都只采用一种方法,就是突然出现在他们脑海中的方法。提出第二个同样可行的设计。对比两者,解释为什么一个比另一个更好。简要列出第二种设计作为备选方案,并说明为什么决定不用它。
架构
应用架构之道:分离业务逻辑和技术细节任何事物都是规则性和随机性的组合。规范的意义就在于我们可以将规则性的东西固化下来,尽量减少随心所欲带来的复杂度,一致性可以降低系统复杂度。从命名到架构皆是如此,而架构本身就是一种规范和约束,破坏这个约束,也就破坏了架构。
架构是什么
从方法到思维:什么是应用逻辑架构的正确姿势? 作者一直尝试对“架构是什么”进行有一定高度的提炼。发现了一句话:The fundamental organization of a system, embodied in its components, their relationships to each other and the environment, and the principles governing its design and evolution. 根据这个定义,Architecture = Structure of Components + Relationships + Principles&Guidelines,我们在架构中需要:
- 职责明确的模块或者组件
- 组件直接的关联关系非常明确
- 需要有约束和指导原则
架构要解决的问题
语言、数据结构、算法、中间件使用等属于硬的内容,比如容易表述,也容易衡量。而架构设计,系统的“三高”则属于“隐性问题”
- 因为一个系统设计问题导致研发人力的投入和时间成本的增加
- 业务确实很复杂,做新功能有沉重的历史包袱,最终技术拖累业务
架构是针对所有重要问题做出的重要决策。很显然,不同公司不同阶段碰到的问题不同,架构所做的事情自然也不一样。
架构的道
- 对于技术问题,主要指高并发、高可用和一致性方面
- 对于业务问题,主要指业务的需求分析和业务建模
道 | 术 |
---|---|
内功心法 | 外功招式 |
知(理论) | 行(实践) |
问题 | 答案 |
当你不具体负责某一个业务或系统,如何看待架构,如何让架构体现价值
我对云原生软件架构的观察与思考软件架构主要目标是解决下列挑战:
- 控制复杂性。由于业务的复杂性,需要我们用更好的手段帮助研发组织克服认知障碍,更好的分工协作。分而治之,关注点分离等手段皆是如此。PS:容器发布系统就深有体会, 和小伙伴代码风格不一致,一开始设计没做好,就是单纯的实现接口,新需求多个地方都可以加或改,导致最后代码完全 随着一个人的风格失控
- 应对不确定性。业务在快速发展,需求在不断变化。即使再完美的软件架构,然而随着时间的推移,团队的变化,软件架构的调整不可避免。读《设计模式》,《微服务设计》等书字里行间写的都是“解耦”两字,让我们关注架构中确定性和不确定性的分离,提升架构的稳定性和应变能力。PS:此外一定要明确核心设计,判断核心设计是否考虑过、cover到新需求,如果cover 不到,就要更新设计,而不是勉强实现。在软件设计的摸索阶段,尤其要避免复杂性
- 管理系统性风险。管理系统中的确定性以及不确定性风险,规避已知陷阱,对未知的风险做好准备。
更抽象一下就是:业务对技术有什么要求?支持更多业务,响应更快,能服务越来越多人(更强),低成本。资源伸缩、资源成本(这两个阿里已接近解决)、研发效率。
WWW的发明人蒂姆.伯纳斯.李谈到设计原理时说过:简单性和模块化是软件工程的基石;分布式和容错性是互联网的生命。
- 有了清晰的可衡量的系统建设的目标,最容易遗漏的一点,是可以做一个用来跟踪系统建设效果的系统
- 从可衡量的目标映射到技术层面要去解决的核心问题,是很需要技术功底的。如果要达成系统设计的可衡量的目标,到底面临了一些什么核心问题,只有明白了面临什么核心问题,才能更加明确的进行系统设计来解决这些问题。
- 访问量大的系统最重要的是对整个系统的处理过程要非常的清楚,因为在访问量大的情况下,一些小的问题有可能会放大成很大的问题,进而到故障,所以访问量大的系统对技术的可控性要求是极高的
单点带来的性能、容量瓶颈 以及研发协作效率瓶颈 逼着进行了分布式改造。
云时代的软件架构走向何方?
- 第一点是弹性,我可以有高峰就用、没有高峰就退。举个例子,单机多线程编程往往不是面向弹性的,而基于 MQ 的设计,消费者算力不够时可以通过水平扩容解决,便是面向弹性的设计。
- 第二点,业务研发团队会越来越不关注下面是什么,越来越脱离下面这一层。一个新人加入进来,可以不管那么多context就可以去实现业务需求。
具体的架构分类
系统架构
- 微服务
- 一个问题在一个进程的多线程间存在,多半也在一台机器的多进程,多台机器的多进程间存在,而解决问题的思路多半是一样的,这也是学习基础的必要性所在。比如一分钟实现分布式锁
谈谈互联网后端基础设施要点:
- Api网关: nginx ==> APISIX
- 业务应用和后端基础框架
- 缓存、数据库、搜索引擎、消息队列、文件存储
- 统一认证中心 单点登录系统
- 统一配置中心
- 服务治理框架
- 统一日志服务
- 数据基础设施
- 故障监控
这里的后端基础设施主要指的是应用在线上稳定运行需要依赖的关键组件/服务等。开发或者搭建好以上的后端基础设施,一般情况下是能够支撑很长一段时间内的业务的。此外,对于一个完整的架构来说,还有很多应用感知不到的系统基础服务,如负载均衡、自动化部署、系统安全等
业务架构
业务的本质是模型。如果我们能基于复杂业务场景抽象出领域模型或者基于复杂业务场景做流程编排,做好分层,不仅反映你对业务认知的深度,也反映了你的技术深度。
《软件架构设计》为什么要区分“业务架构”和“技术架构”?要时刻意识到我们面对的是业务问题还是技术问题。
- 能够通过架构设计降低业务代码修改(对应功能的增删改)的难度吗?
- 如果能,如何通过架构设计降低业务代码修改的难度?
方法论
很多时候会遇到这样的情况:一个函数写了几百行代码,里面的if-else写了很多,计算各种业务规则。另一个人接手后,分析了好几天,才把业务逻辑彻底理清楚。这个问题表面上看是代码写的不规范、要重构。从根本上讲,就是重要逻辑隐藏在代码里面,没有”显性“的表达出来。这只是一个函数,推广到类、模块、系统,是同样的道理。所以,建模的本质就是:把重要的东西进行显性化,进而把这些显性化的构造块互相串联起来,组成一个体系。让它在”设计图纸“上可见,而不是分析完代码才能看出来。重要的东西找到了,如何显性化呢?其实就是”命名“
毕玄:架构跟写代码不同,架构最大的问题是如果解决思路有问题,最后的返工可能非常吓人。阿里在这个地方犯过无数错误。以前做分布式的时候,我们只知道要做成分布式,但我们没有想清楚,一个公司的整个系统换成分布式以后,对团队会带来什么挑战?会有哪些问题?这些如果在架构层面没有解决,后面再解决就很难。现在我们会说“见过猪跑是很重要的”。以前我们觉得见过猪跑有什么重要的,反正我现在没想好,以后可以再补嘛,我可以慢慢练成见过猪跑。但是架构这玩意,你现在没看到,未来要补的时候代价可能极大。所以架构师,对视野的要求非常高。架构的“看到”和“做到”,哪个要求会更高一点?不是一个维度,因为“看到”有些时候是经历问题,另一个就是天花板问题,你有没有办法知道天花板。中国其实很多人并不知道天花板,有人会说看一些大会就可以了,认为大会展示的是天花板。但其实可能根本不是。而且现在大会里还有很多商业目的,就更完蛋,其实他就是忽悠你的,在带节奏,但你不一定知道,因为你外行,这很正常。因为对公司来讲,如果一个架构师不知道天花板,肯定不是个足够好的架构师。以前很多人会在 PPT 上写,我的解决方案是全世界最好的,但你得说清楚你为什么最好,如果你有论证,那我们可以认。或者你说现在不是最好的,但你知道自己的位置,这种也可以,因为这个跟你公司的工程状况有关,工程落地是有节奏问题的,知道最好的是那样,只是我现在做不到,没关系,所有人都这样。如果知道天花板了,就不怕,不知道,你可能也不怕,但是对公司来讲就是一个很可怕的不怕。
因为工程说白了,毕竟不是科学难题,做工程,实在不行是可以试出来的,只是节奏会长,而且有可能不那么可控,成本比较高。这个主要看信不信,你自己觉得可以搞,就可以。我们面试判断的核心就是看你对自己项目背后技术的理解程度,包括这个项目的问题、你的解法、业界对这个问题的解法、最后你为什么选择了这个方法而没有选择业界的方法。如果你能回答得非常好,说明你的选择做得非常理性,这种我们觉得简直是太完美的候选人了。但事实上知道天花板的人很少了,这是要花精力的。很多人不愿意干,觉得没有必要,不就是个需求?我干了就行了,你管我怎么干的,先不先进什么的都不重要。但是有些对技术非常有热情的人,他其实很有兴趣去了解,这个差别非常大的,而且很明显。有时你被推到了这个位置,不得不去解决这个问题。有些人是这样成长起来的,很正常。但这就太看命了,而且对公司来讲,可能会稍微有点问题,因为问题你是解了,但是解法可能有问题,最后会给公司埋下巨大的坑。所以回顾当年,大家都觉得淘宝做得特别好,但事实上我们一帮人看,都觉得自己做的简直了糟糕到不行,有些就是我们当时埋下的坑。但如果让我们再去做,会完全不一样,这说明我们确实比当年更好,因为我们现在是见过猪跑的,也知道天花板在哪里。工程的很多问题,没有经历,凭空想是想不出来的,比如阿里这么大体量,他在技术上到底面临了什么问题,我们在里面都不一定能想得出这个问题是啥,外围就更不提。所以很多人很难成长起来,因为做一个商业系统的机会就很少,你说你在家里想一个商业的系统是怎么做出来的,会面临什么问题,说实话这就是空想,跟这些真正经历过的人去比是不大可能的。
典型/非典型架构
-
典型架构:browser—server,app-server
- 关于互联网“一致性”架构设计的一切
- 互联网分层架构的本质 文章要点:互联网分层架构的本质,是数据的移动;互联网分层架构中,数据的传输格式(协议)与数据在各层次的形态很重要;互联网分层架构演进的核心原则与方法:封装与复用
通用设计
- 满足业务需求
-
- ip耦合:使用内网域名代替内网ip
- 公共库耦合:业务个性强的垂直拆分,公共特性强的下沉服务化
- 数据库耦合:垂直切分与服务化
- 服务化耦合:剥离业务代码上浮
- 消息通知耦合:MQ
- 下游扩容耦合:配置中心
互联网架构:屡试不爽的架构三马车:微服务、消息队列和定时任务
架构老化
架构老化源于什么?在我们不断给系统添加各种新功能的时候,往往会遇到功能需求的实现方式不在当初框架设定的范围之内,于是很多功能代码逸出框架的范围之外。这些散落在各处的代码,把系统绞得支离破碎。久而久之,代码就出现老化,散发出臭味。代码老化的标志,是添加功能越来越难,迭代效率降低,问题却是持续不断,解决了一个问题却又由此生出好几个新问题。在理想的情况下,如果我们坚持以 “最小化的核心系统 + 多个相互正交的周边系统” 这个指导思想来构建应用,那么代码就很难出现老化。
从架构的过去看未来
架构领域经历了快速演进的十年。架构领域在整个互联网的技术栈是偏底层的,但过去十年架构领域的演进速度,一点都不亚于应用开发,甚至移动端开发的速度。比如容器,新型的数据库,新型的中间件,大规模集群的调度,以及系统跟算法的结合。比如
- 容器
- 数据库,数据库作为基础架构非常核心的组成部分,在过去的十年间里面有一个显著的特点是从大一统的一元的数据库逐渐走向多元,逐渐的走向为不同的应用场景而定制。以电商为例,一般来说会用 MySQL 以及 MySQL 的中间件,作为最关键的结构化存储,但同时会配上内存 KV Store 做加速、用检索型数据库做全文检索,用时间序列数据库做海量数据的监控采集和分析,等等。从 DB 底层核心技术来看,跨地域复制且强一致复制、计算与存储分离、从以磁盘为中心到以内存为中心,是三个非常显著的技术变迁。
- 系统跟算法的结合越来越紧密,系统跟算法一起形成一家公司的技术的基石,系统相当于是骨架,而算法给骨架注入了灵魂。
软件架构,唯一不变的就是变化,但变化又分成了波动与趋势,所以对趋势的把握显得尤为重要。未来的两个预测
- 架构智能化
- 混合多云,接下来 5 到 10 年,很多大中型企业,他们重要的业务一定会横跨自己的数据中心和不同云服务商的数据中心。一定会有框架出现来屏蔽底层的这些差异与复杂性
周志明:软件架构风格从大型机(Mainframe),发展到了多层单体架构(Monolithic),到分布式(Distributed),到微服务(Microservices),到服务网格(Service Mesh),到无服务(Serverless)……你能发现,在技术架构上确实呈现出“从大到小”的发展趋势。在我看来,架构演变最重要的驱动力,或者说产生这种“从大到小”趋势的最根本的驱动力,始终都是为了方便某个服务能够顺利地“死去”与“重生”而设计的。流水不腐,有老朽、有消亡、有重生、有更迭,才是正常生态的运作合理规律。只要在整体架构设计中,有恰当的、自动化的错误熔断、服务淘汰和重建的机制,那在系统外部来观察,它在整体上仍然有可能表现出稳定和健壮的服务能力。
其它
毕玄做系统设计的套路:系统设计的目的 -> 系统设计的目标 -> 围绕目标的核心设计 -> 围绕核心设计形成的设计原则 -> 各子系统、模块的详细设计。最重要的是定义目的,做一套架构之前他要告诉所有人,这次为什么要做架构级的改造?目的是我做这件事情是为了什么,但是目标是我怎么考核你做到,其实是个指标。
- 解决思路有很多种,那你为什么选择这种?你的思路是不是最好的?如果不是最好的,你要知道最好是什么。很多架构师是讲不出这个逻辑的。他为什么要把框画成那样,是因为别人把框画成了那样,他只是套用了一下而已。这就不叫做架构设计,这只是复制一下。所以架构师通常是会讲的人,因为架构师是需要传达的。这一步感觉是不好培训的,我们只能讲案例,因为选择涉及很多方面,像技术选型需要你“见过猪跑”,还有工程落地问题,你要想到底哪几个地方是一定要解决的,哪些在当前阶段是不重要的,这就是架构师的取舍。你不能说我什么都要做好,那不可能。
- 落地最重要,但在技术先进度、方案效果和工程落地等等方面上,很多人对优先级的看法可能不太一样?毕玄:为什么很多技术很好的人在一家公司做不成事情?最大的问题是他不能接受妥协。像我们做统一调度也是,当时决定做两个调度器,在线的 Sigma,离线的 Fuxi,然后中间有个所谓的零层来做两层的交互,后来应该是 19 年合在一起了就是 ASI。最早我们也有纠结,要不要做一个统一调度去同时支持在线和离线。很多人从技术梦想上讲应该先统一,但我坚决不同意,我就跟团队讲这不光是技术问题,还有工程问题。如果统一成一套,光做这套调度器可能就 3 年了,这 3 年里我们不会看到任何成果,但我要的是 3 年内看到类似 Borg 的混部带来的整体收益,有了收益,以后自然有机会去实现技术梦想,如果没有收益,可能公司隔 2 年觉得这项目不值得干,直接就不让我们干了,这很正常。我当然也知道有另外一套更好看的,但关键是要判断工程节奏,以及判断如果用这种丑陋的方案是不是做不到业务效果,如果做不到,当然就是另外一个事,关键它不是阻碍的点,对不对?那干嘛挑战难度。反正我觉得挺好的,能做成就行了,你管我什么方案,而且这个方案我会逐步变完美的。
- 因为一个大系统的架构,不是光有你,你下面还有很多系统的架构师,关键是这些人听不听你的。之前我们聊架构师的判断都是主观的,这个问题在当前阶段,我讲的所有方法,另外一个架构师可能不这么认为,他觉得我们应该用另外一个更漂亮的方法,但我可能偏务实,这样双方很容易产生冲突。所以这个大架构师能不能控制一批架构师的想法,让他们听你的,在大公司是一个巨大的挑战。一个新人上来,别人觉得你又没做过,不靠谱。像我是老人,我干过,你们都没干过有什么权利跟我说,我就能说:“我承认你说的挺好,但是你必须按我说的干。”所以架构师的培养为什么很难,尤其大架构师,因为他是以战培养出来的。但战又很少。
- 那程序员的最终归宿是架构师是真的吗?毕玄:不会,这成长路径有问题。程序员成长路径的一条就是继续做程序员,这还是得一直做下去的,另外确实有些程序员成长为了架构师,但其实他就是一个兼职,研发工程师兼架构师角色。如果谁说我就只设计系统,这人很多时候没活干的,因为系统不需要老设计。万一你真的设了这个岗位,那完蛋了,因为这个人就会老想,会凭空创造出来一些需求,这就尴尬了。
- 核心是文化不一样,蚂蚁是规划文化,淘宝是赛马文化,这就决定了两家公司有非常大的风格差异。我认为跟整个商业竞争有很大关系,就是在你的商业竞争面上,你到底认为技术在里面是什么地位?如果技术只是个支撑,那就一点都不重要了,如果技术就是你的竞争力,那你的看法就会变,会觉得技术人才的培养、存留都很重要。像蚂蚁更规划一些,也有是金融行业的原因。蚂蚁会刻意培养,他会有一个盘点,比如说你现在是负责这个系统的架构师,他如果觉得你有潜质负责整个业务板块,过一两年就会把你调岗,直接调去另外一个系统的团队里,这样你不就两个系统都熟了。蚂蚁很多大架构师都是这样培养出来的,有目的地调整人员组织结构。淘宝是没有组织培养的,所以这个事情就乱套了,只能靠项目,但靠项目就很难,大家都是被临时弄上去的,就会硬做。很多人就是在一个系统干到死,他根本没有机会了解另外一个系统是怎么回事,他去哪了解?所以我们觉得,架构师这玩意儿是个组织问题。
一个架构师的感悟因为软件是为了满足客户的功能性需求的,所以很多设计人员可能会认为架构是由要实现的功能性需求决定的。但实际上真正决定软件架构的其实是非功能性需求。架构师要更加关注非功能性需求,常见的非功能性包括:性能,伸缩性,扩展性和可维护性等,甚至还包括团队技术水平和发布时间要求。能实现功能的设计总是有很多,考虑了非功能性需求后才能筛选出最合适的设计。PS: 先广度遍历提方案,再剪枝筛选最终方案。
在软件架构领域有一句名言:“架构并不由系统的功能决定,而是由系统的非功能属性决定”。这句话直白的解释就是:假如不考虑性能、健壮性、可移植性、可修改性、开发成本、时间约束等因素,用任何的架构、任何的方法,系统的功能总是可以实现的,项目总是能开发完成的,只是开发时间、以后的维护成本、功能扩展的容易程度不同罢了。