《凤凰架构》阅读笔记
《凤凰架构》阅读笔记
我曾经在一位学长的推荐下读到了周志明老师的《凤凰架构》, 不仅内容质量极高. 而且阅读起来就像小说一样畅快. 我想记录一些书中很棒的想法, 以及我的思考.
非业务功能下沉到基础设施
业务代码本身已经足够复杂了, 如果一些技术性的代码(例如去重, 事务, 日志, 负载均衡, 数据同步)也参与进来就会显得层次不清晰.
此时最好把非业务的功能下沉到基础设施层面去实现, 例如使用 mysql 的 ON UPDATE CURRENT_TIMESTAMP
来给updateTime
字段自动赋值, 而不是每次写数据时手动将其赋值为当前时间戳.
好处是代码可以专注于业务实现, 用基础设施来代替人去实现基础功能也更可靠.
从 SpringCloud 到 k8s 的演进中可以看到, 以前用应用层代码实现的服务发现 / 负载均衡都被集成到了基础设施层面.
Docker 和 Kubernetes 的成功
促使 Docker 的一问世就惊艳世间的,不是什么黑科技式的秘密武器,而是其符合历史潮流的创意与设计理念,还有充分开放的生态运营。可见,在正确的时候,正确的人手上有一个优秀的点子,确实有机会引爆一个时代。
云的时代不能充分利用云的强大能力,这让云计算厂商无比遗憾,也无比焦虑。直到 Kubernetes 横空出世,大家终于等到了破局的希望,认准了这就是云原生时代的操作系统,是让复杂软件在云计算下获得韧性、弹性、可观测性的最佳路径,也是为厂商们推动云计算时代加速到来的关键引擎之一。
Kubernetes 的成功不仅有 Google 深厚的技术功底作支撑,有领先时代的设计理念,更加关键的是 Kubernetes 的出现符合所有云计算大厂的切身利益,有着业界巨头不遗余力的广泛支持,它的成功便是一种必然。
微服务的拆分粒度
微服务粒度的下界是它至少应满足
- 独立——能够独立发布、独立部署、独立运行与独立测试.
- 内聚——强相关的功能与数据在同一个服务中处理.
- 完备——一个服务包含至少一项业务实体与对应的完整操作.
我曾见过一个拆分微服务粒度过细的失败案例: 团队的后端有五个人, 负责的项目拆成了六七个微服务. 服务是分开了可是人还没分开, 团队里的每一个人都必须掌握每一个服务的细节. 服务之间的依赖关系强到一个改动可能牵扯多个服务. 最后还是要用单体架构的思维去开发, 没捞到微服务的好处, 但是却付出了微服务的代价, 例如原来的 dao 层的 crud 不得不再包装一层上升到 rpc 层面.
一个服务, 它需要对外界暴露细节的越少越好. 它所提供的功能应该是简洁且单一的.
微服务粒度的上界是一个 2 Pizza Team 能够在一个研发周期内完成的全部需求范围。
周老师给出了一个公式, 用算法复杂度来理解: 沟通成本和团队规模是呈 n2 的关系的. 一个团队的规模最好限制在 12 人以下(两个披萨能喂饱)
演进式设计
演进式设计与建筑设计的关键区别是,它不像是“造房子”,更像是“换房子”。举个具体的例子你就能明白:
- 在校求学的你住着六人间宿舍;
- 初入职场的你搬进了单间出租屋;
- 新婚燕尔的你买下属于自己的两室一厅;
- 孩子上学时,你换上了大户型的学区房;
- 孩子离家读书时,你也终于走上人生巅峰,换了一套梦想中的大别墅。
对于你住进大别墅的这个过程,后一套房子并不是前一套房子的“升级版本”,两套房子之间只有逻辑意义上继承关系,没有实质血源上的继承关系,你最后的大别墅绝对不是在最初的六人间宿舍基础上添砖加瓦扩建而来的。同理,大型软件的建设是一个不断推倒重来的演进过程,前一个版本对后一个版本的价值在于它满足了这个阶段用户的需要,让团队成功适应了这个阶段的复杂度,可以向下一个台阶迈进。对于最终用户来说,一个能在演进过程中逐步为用户提供价值的系统,体验也要远好于一个憋大招的系统——哪怕这大招最终能成功憋出来,这个道理就如下图这幅关于理想交通工具的漫画所示。
无论事先设计的有多么美好, 随着需求不断增加和人员的更替, 架构的腐化是必然的. 要保持一个系统正常运转, 单纯在原系统上修修补补不能根本解决问题, 必须要阶段性地推倒重来. 即: 演进式设计
一般来说, 我们都很害怕"推倒重来"这个词, 因为这往往意味着原先的方案有误, 导致先前的工作白费.
但是对于一个长生命周期的软件来说, 我们不可能在一开始就考虑到以后遇到的所有可能性. 我们要接受一个事实: 现在的设计只能满足一段时间的需求, 在未来它迟早要被替换. (尽管这对于强迫症/代码洁癖者来说是残酷的)
并不是所有软件一开始就要赶时髦用微服务的, 在初期, 单体架构可能才是最合适的选择. 如果强行使用与需求不符的高级架构, 很可能架构本身的复杂度成了开发的最大阻碍. 可以等到软件足够复杂时, 再进行微服务的拆分, 这并不是一种失败. (你吃完第三个馒头才吃饱, 这并不意味着前两个馒头是没有意义的)
复杂性本身不是洪水猛兽,无法处理的复杂性才是。刀耕火种的封建时代无法想像机器大生产中的复杂协作,蒸汽革命时代同样难以想像数字化社会中信息的复杂流动。先进的生产力都伴随着更高的复杂性,需要有与生产力符合的生产关系来匹配,敏锐地捕捉到生产力的变化,随时调整生产关系,这才是架构师治理复杂性的终极方法。
如何判断一个选择的价值
价值 = (技能收益 + 知识收益) × 提升空间 / 投入成本
- 技能收益:能立即派上用场的技能当然是有价值的. 首先在社会中务实地生存,不涉及是否快乐,先把本分工作做对做好,再追求兴趣选择和机遇发展.
- 知识收益:世界上鲜有“烟囱式”的专业人才,专才的知识体系基本还是“金字塔式”的,在领域里能够显著超过他人高度的前提条件,往往便是拥有着超过他人的知识广度。 学习那些并不会立即派上用场的知识的意义: 当新的信息输入时,如果能在知识体系中快速找到它应该安放的位置,定位它的问题与解题空间,找到它与其他知识点的关联关系,那你接受新信息的认知负荷就降低了,通俗地讲,你就有了比别人更高的学习效率,更敏锐的技术触觉。
- 提升空间:如果一项工作对你来说是个全新的领域,甚至能称为是一项挑战,那风险的背后往往也蕴含有更高的收益。如果你真的能把它做出来, 这就意味着你的知识体系得到了巨大的拓展, 而不是在原来的体系中把五楼加高成六楼.
- 投入成本:在这门架构课程中,我经常讲的一个词是“权衡”,经常说的一句话是“凡事不能只讲收益不谈成本”,在我的价值模型里,收益大小也是必须在确定的成本下才有衡量比较的意义。这里的成本,既包括你花费的时间、金钱与机会,也包括你投入的知识、精神与毅力。 强调投入成本,是希望你不要去钻牛角尖,如果一项知识或技能,你学习起来非常吃力,花费大力气弄懂之后过一段时间却又会迅速遗忘掉,这很可能是因为你既没有实际应用它的场景,知识体系中也没有建立好掌握它的稳固的前置基础。这种就属于你目前还拿不动的东西,不妨趁早放手,先做好减法,才能做好加法;也不必觉得可惜,如果它对你来说是必要的,一定还会再次出现,想躲也躲不掉。
用输出去倒逼输入
我所践行的知识整理方法是“将思考具象化”,思考本是外界不可知的,其过程如何、其结果如何只有你自己心里才清楚。如果不把自己思考的内容输出给他人,很容易就会被自己所欺骗,误以为自己已经理解得足够完备了。
开篇中,我便提到了撰写这门课程的目的:做技术不仅要去看、去读、去想、去用,更要去说、去写。将自己“认为掌握了的”知识叙述出来,能够说得清晰有条理,讲得理直气壮;能够让他人听得明白,释去心中疑惑;能够把自己的观点交予别人的审视,乃至质疑,在此过程之中,会挖掘出很多潜藏在“已知”背后的“未知”。
这个目的也是它成为免费公益课的原因:课程本身就是我对自己知识体系的整理的成果,是我思考的具象化表现,这件事情中,我自己是最大的受益者,其后的极客时间课程,以及出版的纸质书籍,都可算是额外的收获,这样看来,经济上的回报也就不那么重要了。