软件架构来到 SOA 时代,许多概念、思想都已经能在今天微服务中找到对应的身影了,譬如服务之间的松散耦合、注册、发现、治理,隔离、编排,等等。这些在今天微服务中耳熟能详的名词概念,大多数也是在分布式服务刚被提出时就已经可以预见的困难点。SOA 针对这些问题,甚至是针对“软件开发”这件事情本身,都进行了更加系统性、更加具体的探索。
- “更具体”体现在尽管 SOA 本身还是属抽象概念,而不是特指某一种具体的技术,但它比单体架构和前面所列举的三种架构模式的操作性要更强,已经不能简单视其为一种架构风格,而是可以称为一套软件设计的基础平台了。它拥有领导制定技术标准的组织 Open CSA;有清晰软件设计的指导原则,譬如服务的封装性、自治、松耦合、可重用、可组合、无状态,等等;明确了采用 SOAP 作为远程调用的协议,依靠 SOAP 协议族(WSDL、UDDI 和一大票 WS-*协议)来完成服务的发布、发现和治理;利用一个被称为企业服务总线(Enterprise Service Bus,ESB)的消息管道来实现各个子系统之间的通信交互,令各服务间在 ESB 调度下无须相互依赖却能相互通信,既带来了服务松耦合的好处,也为以后可以进一步实施业务流程编排(Business Process Management,BPM)提供了基础;使用服务数据对象(Service Data Object,SDO)来访问和表示数据,使用服务组件架构(Service Component Architecture,SCA)来定义服务封装的形式和服务运行的容器,等等。在这一整套成体系可以互相精密协作的技术组件支持下,若仅从技术可行性这一个角度来评判的话,SOA 可以算是成功地解决了分布式环境下出现的主要技术问题。
- “更系统”指的是 SOA 的宏大理想,它的终极目标是希望总结出一套自上而下的软件研发方法论,希望做到企业只需要跟着 SOA 的思路,就能够一揽子解决掉软件开发过程中的全部问题,譬如该如何挖掘需求、如何将需求分解为业务能力、如何编排已有服务、如何开发测试部署新的功能,等等。这里面技术问题确实是重点和难点,但也仅仅是其中的一个方面,SOA 不仅关注技术,还关注研发过程中涉及到的需求、管理、流程和组织。如果这个目标真的能够达成,软件开发就有可能从此迈进工业化大生产的阶段,试想如果有一天写出符合客户需求的软件会像写八股文一样有迹可循、有法可依,那对软件开发者来说也许是无趣的,但整个社会实施信息化的效率肯定会有大幅的提升。
SOA 在 21 世纪最初的十年里曾经盛行一时,有 IBM 等一众行业巨头厂商为其呐喊冲锋,吸引了不少软件开发商、尤其是企业级软件的开发商的跟随,最终却还是偃旗息鼓,沉寂了下去。在稍后的远程服务调用一节,笔者会提到 SOAP 协议被逐渐边缘化的本质原因:过于严格的规范定义带来过度的复杂性。而构建在 SOAP 基础之上的 ESB、BPM、SCA、SDO 等诸多上层建筑,进一步加剧了这种复杂性。开发信息系统毕竟不是作八股文章,过于精密的流程和理论也需要懂得复杂概念的专业人员才能够驾驭。SOA 诞生的那一天起,就已经注定了它只能是少数系统阳春白雪式的精致奢侈品,它可以实现多个异构大型系统之间的复杂集成交互,却很难作为一种具有广泛普适性的软件架构风格来推广。SOA 最终没有获得成功的致命伤与当年的EJB如出一辙,尽管有 Sun Microsystems 和 IBM 等一众巨头在背后力挺,EJB 仍然败于以 Spring、Hibernate 为代表的“草根框架”,可见一旦脱离人民群众,终究会淹没在群众的海洋之中,连信息技术也不曾例外过。
读到这里,你不妨回想下“如何使用多个独立的分布式服务共同构建一个更大型系统”这个问题,再回想下“原始分布式时代”一节中 Unix DCE 提出的分布式服务的设计主旨:“让开发人员不必关心服务是远程还是本地,都能够透明地调用服务或者访问资源”。经过了三十年的技术进步,信息系统经历了巨石、烟囱、插件、事件、SOA 等的架构模式,应用受架构复杂度的牵绊却是越来越大,已经距离“透明”二字越来越远了,这是否算不自觉间忘记掉了当年的初心?接下来我们所谈论的微服务时代,似乎正是带着这样的自省式的问句而开启的。
微服务架构(Microservices)
微服务是一种通过多个小型服务组合来构建单个应用的架构风格,这些服务围绕业务能力而非特定的技术标准来构建。各个服务可以采用不同的编程语言,不同的数据存储技术,运行在不同的进程之中。服务采取轻量级的通信机制和自动化的部署机制实现通信与运维。
“微服务”这个技术名词最早在 2005 年就已经被提出,它是由 Peter Rodgers 博士在 2005 年度的云计算博览会(Web Services Edge 2005)上首次使用,当时的说法是“Micro-Web-Service”,指的是一种专注于单一职责的、语言无关的、细粒度 Web 服务(Granular Web Services)。“微服务”一词并不是 Peter Rodgers 直接凭空创造出来的概念,最初的微服务可以说是 SOA 发展时催生的产物,就如同 EJB 推广过程中催生了 Spring 和 Hibernate 那样,这一阶段的微服务是作为一种 SOA 的轻量化的补救方案而被提出的。时至今日,在英文版的维基百科上,仍然将微服务定义为一种 SOA 的变种形式,所以微服务在最初阶段与 SOA、Web Service 这些概念有所牵扯也完全可以理解,但现在来看,维基百科对微服务的定义已经颇有些过时了。
What is microservices
Microservices is a software development technique — a variant of the service-oriented architecture (SOA) structural style.
微服务是一种软件开发技术,是一种 SOA 的变体形式。
—— Wikipedia,Microservices
微服务的概念提出后,在将近十年的时间里面,并没有受到太多的追捧。如果只是对现有 SOA 架构的修修补补,确实难以唤起广大技术人员的更多激情。不过,在这十年时间里,微服务本身也在思考蜕变。2012 年,在波兰克拉科夫举行的“33rd Degree Conference”大会上,Thoughtworks 首席咨询师 James Lewis 做了题为《Microservices - Java, the Unix Way》的主题演讲,其中提到了单一服务职责、康威定律、自动扩展、领域驱动设计等原则,却只字未提 SOA,反而号召应该重拾 Unix 的设计哲学(As Well Behaved Unix Services),这点仿佛与笔者在前一节所说的“初心与自省”遥相呼应。微服务已经迫不及待地要脱离 SOA 的附庸,成为一种独立的架构风格,也许,未来还将会是 SOA 的革命者。
微服务真正的崛起是在 2014 年,相信阅读此文的大多数读者,也是从 Martin Fowler 与 James Lewis 合写的文章《Microservices: A Definition of This New Architectural Term》中首次了解到微服务的。这并不是指各位一定读过这篇文章,应该准确地说——今天大家所了解的“微服务”是这篇文章中定义的“微服务”。在此文中,首先给出了现代微服务的概念:“微服务是一种通过多个小型服务组合来构建单个应用的架构风格,这些服务围绕业务能力而非特定的技术标准来构建。各个服务可以采用不同的编程语言,不同的数据存储技术,运行在不同的进程之中。服务采取轻量级的通信机制和自动化的部署机制实现通信与运维。”此外,文中列举了微服务的九个核心的业务与技术特征,下面将其一一列出并解读。
- 围绕业务能力构建(Organized around Business Capability)。这里再次强调了康威定律的重要性,有怎样结构、规模、能力的团队,就会产生出对应结构、规模、能力的产品。这个结论不是某个团队、某个公司遇到的巧合,而是必然的演化结果。如果本应该归属同一个产品内的功能被划分在不同团队中,必然会产生大量的跨团队沟通协作,跨越团队边界无论在管理、沟通、工作安排上都有更高昂的成本,高效的团队自然会针对其进行改进,当团队、产品磨合调节稳定之后,团队与产品就会拥有一致的结构。
- 分散治理(Decentralized Governance)。这是要表达“谁家孩子谁来管”的意思,服务对应的开发团队有直接对服务运行质量负责的责任,也应该有着不受外界干预地掌控服务各个方面的权力,譬如选择与其他服务异构的技术来实现自己的服务。这一点在真正实践时多少存有宽松的处理余地,大多数公司都不会在某一个服务使用 Java,另一个用 Python,下一个用 Golang,而是通常会有统一的主流语言,乃至统一的技术栈或专有的技术平台。微服务不提倡也并不反对这种“统一”,只要负责提供和维护基础技术栈的团队,有被各方依赖的觉悟,要有“经常被凌晨 3 点的闹钟吵醒”的心理准备就好。微服务更加强调的是确实有必要技术异构时,应能够有选择“不统一”的权利,譬如不应该强迫 Node.js 去开发报表页面,要做人工智能训练模型时,应该可以选择 Python,等等。
- 通过服务来实现独立自治的组件(Componentization via Services)。之所以强调通过“服务”(Service)而不是“类库”(Library)来构建组件,是因为类库在编译期静态链接到程序中,通过本地调用来提供功能,而服务是进程外组件,通过远程调用来提供功能。前面的文章里我们已经分析过,尽管远程服务有更高昂的调用成本,但这是为组件带来隔离与自治能力的必要代价。
- 产品化思维(Products not Projects)。避免把软件研发视作要去完成某种功能,而是视作一种持续改进、提升的过程。譬如,不应该把运维只看作运维团队的事,把开发只看作开发团队的事,团队应该为软件产品的整个生命周期负责,开发者不仅应该知道软件如何开发,还应该知道它如何运作,用户如何反馈,乃至售后支持工作是怎样进行的。注意,这里服务的用户不一定是最终用户,也可能是消费这个服务的另外一个服务。以前在单体架构下,程序的规模决定了无法让全部人员都关注完整的产品,组织中会有开发、运维、支持等细致的分工的成员,各人只关注于自己的一块工作,但在微服务下,要求开发团队中每个人都具有产品化思维,关心整个产品的全部方面是具有可行性的。