learn-tech/专栏/周志明的架构课/01_原始分布式时代:Unix设计哲学下的服务探索.md
2024-10-16 06:37:41 +08:00

109 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
01 _ 原始分布式时代Unix设计哲学下的服务探索
你好,我是周志明。欢迎你来到“软件架构课”,从今天开始,我们就进入课程的第一个模块“演进中的架构”。
架构并不是被“发明”出来的,而是持续进化的结果。所以在这一模块中,我会借着讨论历史之名,从全局性的视角,来带你一起梳理下微服务的发展历程中,出现的大量技术名词、概念。
我会和你一起去分析,它们都是什么、取代了什么,以及为什么能够在技术发展的斗争中取得成功,为什么会成为软件架构不可或缺的支撑;又或者它们为什么会失败,为什么会逐渐被我们遗忘。
了解了这些技术的时代背景和探索过程,在后续的课程中,我再去讲解它们的原理、它们是如何解决问题的时候,你就能与它们当初的设计思想产生共鸣,能更容易深入理解其本质了。
今天这一讲让我们先把时间拨回到半个世纪之前一起来探讨下计算机最开始进入公众视野的时候在Unix设计哲学的指导下分布式架构的第一次服务化探索的得与失。
Unix的分布式设计哲学-
Simplicity of both the interface and the implementation are more important than any other attributes of the system — including correctness, consistency, and completeness.-
保持接口与实现的简单性,比系统的任何其他属性,包括准确性、一致性和完整性,都来得更加重要。-
—— Richard P. GabrielThe Rise of Worse is Better1991
分布式架构的目标是使用多个独立的分布式服务,来共同构建一个更大型的系统。不过,可能跟绝大多数人心中的认知有点儿差异,分布式系统的设想和它实际的尝试,反而要比你今天所了解的大型单体系统出现的时间更早。
在20世纪70年代末到80年代初计算机科学刚经历了从以大型机为主到向以微型机为主的蜕变计算机也逐渐从一种存在于研究机构、实验室当中的科研设备转变为了存在于商业企业中的生产设备甚至是面向家庭、个人用户的娱乐设备。
这个时候的微型计算机系统通常具有16位寻址能力、不足5MHz兆赫时钟频率的处理器和128KB左右的内存地址空间。比如说著名的英特尔处理器的鼻祖Intel 8086处理器就是在1978年研制成功流行于80年代中期的甚至一直到90年代初期还在生产销售。
不过,因为当时的计算机硬件的运算处理能力还相当薄弱,已经直接妨碍了单台计算机上信息系统软件能够达到的最大规模。所以,为了突破硬件算力的限制,各个高校、研究机构、软硬件厂商,都开始分头探索,想看看到底能不能使用多台计算机共同协作,来支撑同一套软件系统的运行。
这个阶段其实是对分布式架构最原始的探索与研究。你可能会觉得奇怪,计算机科学这个技术发展一日千里的领域,半个世纪之前的研究对今天还能有什么指导意义?那个时候探索的分布式如果是可行的,又怎么会拖到今时今日,软件系统才逐步进入微服务时代?
然而并非如此从结果来看历史局限决定了它不可能一蹴而就地解决分布式的难题但仅从过程来看这个阶段的探索可以称得上是硕果累累、成绩斐然。因为在这个时期提出的很多技术、概念对Unix系统后续的发展甚至是对今天计算机科学的很多领域都产生了巨大而深远的影响直接带动了后续的软件架构演化进程。
我们看一些比较熟悉的例子吧。
比如惠普公司及后来被惠普收购的Apollo在80年代初期提出的网络运算架构Network Computing ArchitectureNCA就可以说是未来远程服务调用的雏形。
再比如,卡内基 · 梅隆大学提出的AFS文件系统Andrew File System可以看作是分布式文件系统的最早实现顺便一提Andrew的意思是纪念Andrew Carnegie和Andrew Mellon
再比如麻省理工学院提出的Kerberos协议是服务认证和访问控制ACL的基础性协议是分布式服务安全性的重要支撑目前包括Windows和macOS在内的众多操作系统的登录、认证功能等等都会利用到这个协议。
而为了避免Unix系统的版本战争在分布式领域中重演负责制定Unix系统技术标准的开放软件基金会Open Software FoundationOSF也就是后来的“国际开放标准组织”就邀请了各个主要的研究厂商一起参与共同制订了“分布式运算环境”Distributed Computing EnvironmentDCE的分布式技术体系。
DCE包括了一整套完整的分布式服务组件的规范与实现。
比如源自NCA的远程服务调用规范Remote Procedure CallRPC在当时被称为是DCE/RPC跟后来不局限于Unix系统的、基于通用TCP/IP协议的远程服务标准ONC RPC一起被认为是现代RPC的共同鼻祖这是Sun公司向互联网工程任务组提交的源自AFS的分布式文件系统Distributed File SystemDFS规范在当时被称为DCE/DFS源自Kerberos的服务认证规范还有时间服务、命名与目录服务就连现在程序中很常用的通用唯一识别符UUID也是在DCE中发明出来的。
因为OSF本身的背景它是一个由Unix开发者组成的Unix标准化组织所以在当时研究这些分布式技术通常都会有一个预设的重要原则也就是在实现分布式环境中的服务调用、资源访问、数据存储等操作的时候要尽可能地透明化、简单化让开发人员不用去过于关注他们访问的方法或者是要知道其他资源是位于本地还是远程。
这样的主旨呢确实非常符合Unix设计哲学有过几个版本的不同说法这里我指的是Common Lisp作者Richard P. Gabriel提出的简单优先“Worse is Better”原则但这个目标其实是过于理想化了它存在一些在当时根本不可能完美解决的技术困难。
“调用远程方法”与“调用本地方法”尽管只是两字之差但要是想能同时兼顾到简单、透明、性能、正确、鲁棒Robust、一致的目标的话两者的复杂度就完全不能相提并论了。
我们先不说,远程方法是不可能做到像本地方法一样,能用内联等传统编译原理中的优化算法,来提升程序运行速度的,光是“远程”二字带来的网络环境下的新问题。
比如说,远程的服务在哪里(服务发现)、有多少个(负载均衡)、网络出现分区、超时或者服务出错了怎么办(熔断、隔离、降级)、方法的参数与返回结果如何表示(序列化协议)、如何传输(传输协议)、服务权限如何管理(认证、授权)、如何保证通信安全(网络安全层)、如何令调用不同机器的服务能返回相同的结果(分布式数据一致性)等一系列问题,就需要设计者耗费大量的心思。
那么面对重重的困难与压力DCE不仅从零开始、从无到有地回答了其中大部分问题构建出了大量的分布式基础组件与协议而且它还真的尽力去做到了相对意义的“透明”。
比如说你在DFS上访问文件如果不考虑性能上的差异的话就很难感受到它与本地磁盘文件系统有什么不同。可是一旦考虑性能上的差异分布式和本地的鸿沟是无比深刻的这是数量级上的差距是不可调和的。
尤其是在那个年代,在机器硬件的限制下,开发者为了让程序在运行效率上可以接受,就只有在方法本身的运行时间很长,可以相对忽略远程调用成本时的情况下,才去考虑使用分布式。如果方法本身的运行时长不够,就要人为地用各种奇技淫巧来刻意构造出这样的场景,比如可能会将几个原本毫无关系的方法打包到一个方法内,一块进行远程调用。
一方面刻意构造长时间运行的方法这本身就与使用分布式来突破硬件算力、提升性能的初衷相互矛盾需要我们小心平衡另一方面此时的开发人员实际上仍然必须无时无刻地都要意识到自己是在编写分布式的程序不能随随便便地踏过本地与远程的界限让软件系统的设计向性能做出妥协让DCE“尽量简单透明”的努力几乎全部付诸东流。
因为本地与远程,无论是从编码、部署,还是从运行效率的角度上看,都有着天壤之别,所以在设计一个能运作良好的分布式应用的时候,就变得需要极高的编程技巧和各方面的知识来作为支撑,这个时候,反而是人员本身对软件规模的约束,超过机器算力上的约束了。
对DCE的研究呢算得上是计算机科学中第一次有组织领导、有标准可循、有巨大投入的分布式计算的尝试。但无论是DCE还是稍后出现的CORBACommon ObjectRequest Broker Architecture公共对象请求代理体系结构我们从结果来看都不能说它们取得了成功。
因为把一个系统直接拆分到不同的机器之中,这样做带来的服务的发现、跟踪、通讯、容错、隔离、配置、传输、数据一致性和编码复杂度等方面的问题,所付出的代价远远超过了分布式所取得的收益。
而亲身经历过那个年代的计算机科学家、IBM院士凯尔 · 布朗Kyle Brown在事后曾经评价道“这次尝试最大的收获就是对RPC、DFS等概念的开创以及得到了一个价值千金的教训某个功能能够进行分布式并不意味着它就应该进行分布式强行追求透明的分布式操作只会自寻苦果”。
原始分布式时代的教训-
Just because something can be distributed doesnt mean it should be distributed. Trying to make a distributed call act like a local call always ends in tears.-
某个功能能够进行分布式,并不意味着它就应该进行分布式,强行追求透明的分布式操作,只会自寻苦果。-
—— Kyle BrownIBM FellowBeyond buzzwords: A brief history of microservices patterns2016
其实从设计角度来看以上的结论是有违Unix哲学的但这也是在当时的现实情况下不得不做出的让步。在当时计算机科学面前有两条通往更大规模软件系统的道路一条路是尽快提升单机的处理能力以避免分布式的种种问题另一条路是找到更完美的解决方案来应对如何构筑分布式系统的问题。
在20世纪80年代正是摩尔定律开始稳定发挥作用的黄金时期微型计算机的性能以每两年就增长一倍的惊人速度在提升硬件算力束缚软件规模的链条很快就松动了我们用单台或者几台计算机就可以作为服务器来支撑大型信息系统的运作了信息系统进入了单体时代而且在未来很长的一段时间内单体系统都将是软件架构的主流。
不过尽管如此对于另外一条路径也就是对分布式计算、远程服务调用的探索开发者们也从没有中断过。关于远程服务调用这个关键问题的历史、发展与现状我还会在服务设计风格的“远程服务调用”部分第7~10讲以现代RPC和RESTful为主角来进行更详细的讲述。而对于在原始分布式时代中遭遇到的其他问题我也还会在软件架构演进的后面几个时代里反复提起它们。
小结
今天我给你介绍了计算机科学对分布式和服务化的第一次探索着重分析了这次探索的主旨思想也就是追求简单、符合Unix哲学的分布式系统以及它当时所面临的困难比如在捉襟见肘的运算能力、网络带宽下设计不得不做出的妥协。
在这个过程中我们接触到了DCE、CORBA等早期的分布式基础架构。其中许多的技术比如远程服务调用、分布式文件系统、Kerberos认证协议等。如果你对这些技术觉得还有点陌生、或者还有很多疑惑没有关系我还会在后面的课程中为你着重介绍。
原始分布式时代提出的构建“符合Unix的设计哲学的”以及“如同本地调用一般简单透明的”分布式系统的这个目标是软件开发者对分布式系统最初的美好愿景。不过迫于现实它会在一定时期内被妥协、被舍弃分布式将会经过一段越来越复杂的发展进程。
但是,到了三十多年以后的今天,随着微服务的逐渐成熟完善,成为大型软件的主流架构风格以后,这个美好的愿景终将还是会重新被开发者拾起。
一课一思
Richard P. Gabriel提出的Unix设计哲学中写到“保持接口与实现的简单性比系统的任何其他属性包括准确性、一致性和完整性都来得更加重要。”
现在你来思考一下今天以微服务为代表的分布式系统是如何看待“简单”的欢迎在留言区分享你的见解我也将会在第5讲“后微服务时代”中带你一起重新审视这个问题。
好,这节课就到这里。如果你身边也有想要或者必须要了解架构的演进的朋友,欢迎你把这一讲的内容分享给她/他。