简介
借助如何学习分布式系统 得来的经验,当一个知识足够复杂,如何学习它本身就很值得玩味
架构类资料
到目前为止,笔者关于架构的几篇文章或笔记
按照许式伟的说法,架构相关的图书大概有几类
- 架构思维类。 通常从一些著名的架构理论讲起,比如开闭原则、单一职责原则等等。其弊端在于过度理论化,而计算机科学归根到底属于工程技术类,应该实践第一。
- 设计模式类。 这类一般上来就进入架构的局部细节,每个模式的来龙去脉并不容易理解。就算理解了某个具体的模式,也很难真正做到活学活用。
- 分布式系统架构设计类。 通常从服务端的通用问题如一致性、高可用、高并发挑战等话题讲起,阐述大型业务系统面临的挑战。这些知识虽然非常有价值,但无法延伸至通用业务架构,对大部分企业的架构实践不具备真正的指导意义。
- 重构类。 主要讲如何如何改进代码,其实是最实用的一类。但在我看来,一个模块最初的地基是最重要的,基本决定了这座大厦能够撑多久,而重构更多侧重于大厦建成之后,在服务于人的前提下怎么去修修补补,延长生命。
也有人主张:最好的软件设计是简单易懂的设计,软件架构被高估,清晰简单的设计被低估
- 拉过来一名同事,在白板上写下你的设计方法。写出你在做什么,为什么要这么做,征求他们的意见
- 设计两种方案,并进行对比。大多数人在设计架构时都只采用一种方法,就是突然出现在他们脑海中的方法。提出第二个同样可行的设计。对比两者,解释为什么一个比另一个更好。简要列出第二种设计作为备选方案,并说明为什么决定不用它。
架构
应用架构之道:分离业务逻辑和技术细节任何事物都是规则性和随机性的组合。规范的意义就在于我们可以将规则性的东西固化下来,尽量减少随心所欲带来的复杂度,一致性可以降低系统复杂度。从命名到架构皆是如此,而架构本身就是一种规范和约束,破坏这个约束,也就破坏了架构。
架构是什么
从方法到思维:什么是应用逻辑架构的正确姿势? 作者一直尝试对“架构是什么”进行有一定高度的提炼。发现了一句话: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网关
- 业务应用和后端基础框架
- 缓存、数据库、搜索引擎、消息队列、文件存储
- 统一认证中心 单点登录系统
- 统一配置中心
- 服务治理框架
- 统一日志服务
- 数据基础设施
- 故障监控
这里的后端基础设施主要指的是应用在线上稳定运行需要依赖的关键组件/服务等。开发或者搭建好以上的后端基础设施,一般情况下是能够支撑很长一段时间内的业务的。此外,对于一个完整的架构来说,还有很多应用感知不到的系统基础服务,如负载均衡、自动化部署、系统安全等
业务架构
业务的本质是模型。如果我们能基于复杂业务场景抽象出领域模型或者基于复杂业务场景做流程编排,做好分层,不仅反映你对业务认知的深度,也反映了你的技术深度。
《软件架构设计》为什么要区分“业务架构”和“技术架构”?要时刻意识到我们面对的是业务问题还是技术问题。
- 能够通过架构设计降低业务代码修改(对应功能的增删改)的难度吗?
- 如果能,如何通过架构设计降低业务代码修改的难度?
方法论
很多时候会遇到这样的情况:一个函数写了几百行代码,里面的if-else写了很多,计算各种业务规则。另一个人接手后,分析了好几天,才把业务逻辑彻底理清楚。这个问题表面上看是代码写的不规范、要重构。从根本上讲,就是重要逻辑隐藏在代码里面,没有”显性“的表达出来。这只是一个函数,推广到类、模块、系统,是同样的道理。所以,建模的本质就是:把重要的东西进行显性化,进而把这些显性化的构造块互相串联起来,组成一个体系。让它在”设计图纸“上可见,而不是分析完代码才能看出来。重要的东西找到了,如何显性化呢?其实就是”命名“
典型/非典型架构
-
典型架构:browser—server,app-server
- 关于互联网“一致性”架构设计的一切
- 互联网分层架构的本质 文章要点:互联网分层架构的本质,是数据的移动;互联网分层架构中,数据的传输格式(协议)与数据在各层次的形态很重要;互联网分层架构演进的核心原则与方法:封装与复用
通用设计
- 满足业务需求
-
- ip耦合:使用内网域名代替内网ip
- 公共库耦合:业务个性强的垂直拆分,公共特性强的下沉服务化
- 数据库耦合:垂直切分与服务化
- 服务化耦合:剥离业务代码上浮
- 消息通知耦合:MQ
- 下游扩容耦合:配置中心
互联网架构:屡试不爽的架构三马车:微服务、消息队列和定时任务
架构老化
架构老化源于什么?在我们不断给系统添加各种新功能的时候,往往会遇到功能需求的实现方式不在当初框架设定的范围之内,于是很多功能代码逸出框架的范围之外。这些散落在各处的代码,把系统绞得支离破碎。久而久之,代码就出现老化,散发出臭味。代码老化的标志,是添加功能越来越难,迭代效率降低,问题却是持续不断,解决了一个问题却又由此生出好几个新问题。在理想的情况下,如果我们坚持以 “最小化的核心系统 + 多个相互正交的周边系统” 这个指导思想来构建应用,那么代码就很难出现老化。
从架构的过去看未来
架构领域经历了快速演进的十年。架构领域在整个互联网的技术栈是偏底层的,但过去十年架构领域的演进速度,一点都不亚于应用开发,甚至移动端开发的速度。比如容器,新型的数据库,新型的中间件,大规模集群的调度,以及系统跟算法的结合。比如
- 容器
- 数据库,数据库作为基础架构非常核心的组成部分,在过去的十年间里面有一个显著的特点是从大一统的一元的数据库逐渐走向多元,逐渐的走向为不同的应用场景而定制。以电商为例,一般来说会用 MySQL 以及 MySQL 的中间件,作为最关键的结构化存储,但同时会配上内存 KV Store 做加速、用检索型数据库做全文检索,用时间序列数据库做海量数据的监控采集和分析,等等。从 DB 底层核心技术来看,跨地域复制且强一致复制、计算与存储分离、从以磁盘为中心到以内存为中心,是三个非常显著的技术变迁。
- 系统跟算法的结合越来越紧密,系统跟算法一起形成一家公司的技术的基石,系统相当于是骨架,而算法给骨架注入了灵魂。
软件架构,唯一不变的就是变化,但变化又分成了波动与趋势,所以对趋势的把握显得尤为重要。未来的两个预测
- 架构智能化
- 混合多云,接下来 5 到 10 年,很多大中型企业,他们重要的业务一定会横跨自己的数据中心和不同云服务商的数据中心。一定会有框架出现来屏蔽底层的这些差异与复杂性
周志明:软件架构风格从大型机(Mainframe),发展到了多层单体架构(Monolithic),到分布式(Distributed),到微服务(Microservices),到服务网格(Service Mesh),到无服务(Serverless)……你能发现,在技术架构上确实呈现出“从大到小”的发展趋势。在我看来,架构演变最重要的驱动力,或者说产生这种“从大到小”趋势的最根本的驱动力,始终都是为了方便某个服务能够顺利地“死去”与“重生”而设计的。流水不腐,有老朽、有消亡、有重生、有更迭,才是正常生态的运作合理规律。只要在整体架构设计中,有恰当的、自动化的错误熔断、服务淘汰和重建的机制,那在系统外部来观察,它在整体上仍然有可能表现出稳定和健壮的服务能力。
其它
一个架构师的感悟因为软件是为了满足客户的功能性需求的,所以很多设计人员可能会认为架构是由要实现的功能性需求决定的。但实际上真正决定软件架构的其实是非功能性需求。架构师要更加关注非功能性需求,常见的非功能性包括:性能,伸缩性,扩展性和可维护性等,甚至还包括团队技术水平和发布时间要求。能实现功能的设计总是有很多,考虑了非功能性需求后才能筛选出最合适的设计。PS: 先广度遍历提方案,再剪枝筛选最终方案。
在软件架构领域有一句名言:“架构并不由系统的功能决定,而是由系统的非功能属性决定”。这句话直白的解释就是:假如不考虑性能、健壮性、可移植性、可修改性、开发成本、时间约束等因素,用任何的架构、任何的方法,系统的功能总是可以实现的,项目总是能开发完成的,只是开发时间、以后的维护成本、功能扩展的容易程度不同罢了。