Service-Oriented Architecture,面向服务的架构。面向服务的架构是一次具体地、系统性地成功解决分布式服务主要问题的架构模式。了解SOA架构前,先了解三种比较有代表性的服务拆分的架构模式,这些架构模式是SOA演化过程的中间产物,也是SOA架构出现的必要前提。
信息烟囱又名信息孤岛(Information Island),使用这种架构的系统也被称为孤岛式信息系统或者烟囱式信息系统。它指的是一种完全不与其他相关信息系统进行互操作或者协调工作的设计模式。这样的系统其实并没有什么“架构设计”可言。接着上一节中企业与部门的例子来说,如果两个部门真的完全不会发生任何交互,就并没有什么理由强迫它们必须在一栋楼里办公;两个不发生交互的信息系统,让它们使用独立的数据库和服务器即可实现拆分,而唯一的问题,也是致命的问题是,企业中真的存在完全不发生交互的部门吗?对于两个信息系统来说,哪怕真的毫无业务往来关系,但系统的人员、组织、权限等主数据,会是完全独立、没有任何重叠的吗?这样“独立拆分”“老死不相往来”的系统,显然不可能是企业所希望见到的。
微内核架构也被称为插件式架构(Plug-in Architecture)。既然在烟囱式架构中,没有业务往来关系的系统也可能需要共享人员、组织、权限等一些的公共的主数据,那不妨就将这些主数据,连同其他可能被各子系统使用到的公共服务、数据、资源集中到一块,成为一个被所有业务系统共同依赖的核心(Kernel,也称为 Core System),具体的业务系统以插件模块(Plug-in Modules)的形式存在,这样也可提供可扩展的、灵活的、天然隔离的功能特性,即微内核架构,如图所示。
这种模式很适合桌面应用程序,也经常在 Web 应用程序中使用。任何计算机系统都是由各种软件互相配合工作来实现具体功能的,本节列举的不同架构实现的软件,都可视作整个系统的某种插件。对于平台型应用来说,如果我们希望将新特性或者新功能及时加入系统,微内核架构会是一种不错的方案。微内核架构也可以嵌入到其他的架构模式之中,通过插件的方式来提供新功能的定制开发能力,如果你准备实现一个能够支持二次开发的软件系统,微内核也会是一种良好的选择。不过,微内核架构也有它的局限和使用前提,它假设系统中各个插件模块之间是互不认识,不可预知系统将安装哪些模块,因此这些插件可以访问内核中一些公共的资源,但不会直接交互。可是,无论是企业信息系统还是互联网应用,这一前提假设在许多场景中都并不成立,我们必须找到办法,既能拆分出独立的系统,也能让拆分后的子系统之间顺畅地互相调用通信。
为了能让子系统互相通信,一种可行的方案是在子系统之间建立一套事件队列管道(Event Queues),来自系统外部的消息将以事件的形式发送至管道中,各个子系统从管道里获取自己感兴趣、能够处理的事件消息,也可以为事件新增或者修改其中的附加信息,甚至可以自己发布一些新的事件到管道队列中去,如此,每一个消息的处理者都是独立的,高度解耦的,但又能与其他处理者(如果存在该消息处理者的话)通过事件管道进行互动,如图所示。
SOA 的概念最早由 Gartner 公司在 1994 年提出,当时的 SOA 还不具备发展的条件,直至 2006 年情况才有所变化,由 IBM、Oracle、SAP 等公司共同成立了 OSOA 联盟(Open Service Oriented Architecture),用于联合制定和推进 SOA 相关行业标准。2007 年,在结构化资讯标准促进组织(Organization for the Advancement of Structured Information Standards,OASIS)的倡议与支持下,OSOA 由一个软件厂商组成的松散联盟,转变为一个制定行业标准的国际组织,联合 OASIS 共同新成立了的Open CSA组织(Open Composite Services Architecture),这便是 SOA 的官方管理机构。
软件架构来到 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 等的架构模式,应用受架构复杂度的牵绊却是越来越大,已经距离“透明”二字越来越远了,这是否算不自觉间忘记掉了当年的初心?接下来我们所谈论的微服务时代,似乎正是带着这样的自省式的问句而开启的。
其实“微服务”这个词儿,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 microservicesMicroservices is a software development technique — a variant of the service-oriented architecture (SOA) structural style.—— Wikipedia, Microservices
但我们现在再来看,维基百科对微服务的定义,其实已经有些过时了。微服务的概念提出后,将近10年的时间里面,都并没有受到太多的追捧,如果只是对现有SOA架构的修修补补,确实是难以唤起广大技术人员的更多激情了。不过,在这10年时间里,微服务本身也在思考、蜕变。
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》中首次了解到微服务的,并不是指各位一定读过这篇文章,或者准确地说,今天各位所了解的“微服务”是这篇文章中提出的“微服务”。在此文中,定义了现代微服务的概念:“微服务是一种通过多个小型服务组合来构建单个应用的架构风格,这些服务围绕业务能力而非特定的技术标准来构建。各个服务可以采用不同的编程语言,不同的数据存储技术,运行在不同的进程之中。服务采取轻量级的通讯机制和自动化的部署机制实现通讯与运维”。此外,文中列举出了微服务的九个核心的业务与技术特征,笔者将其一一列出并解读如下:
《Microservices》一文中对微服务特征的描写已经相当具体了,此文中除了定义的微服务是什么,还专门申明了微服务不是什么——微服务不是SOA的变体或衍生品,应该明确地与SOA划清了界线,不再贴上任何SOA的标签。如此,微服务的概念才算是一种真正丰满、独立、具体的架构风格,为它在未来的几年时间里如明星一般闪耀崛起于技术舞台铺下了理论基础。
Microservices and SOA
This common manifestation of SOA has led some microservice advocates to reject the SOA label entirely, although others consider microservices to be one form of SOA , perhaps service orientation done right. Either way, the fact that SOA means such different things means it’s valuable to have a term that more crisply defines this architectural style
由于与SOA具有一致的表现形式,这让微服务的支持者更加迫切地拒绝再被打上SOA的标签,尽管有一些人坚持认为微服务就是SOA的一种变体形式,也许从面向服务方面这个方面来说是对的,但无论如何,SOA与微服务都是两种不同的东西,正因如此,使用一个别的名称来简明地定义这种架构风格就显得更有必要。
—— Martin Fowler / James Lewis,Microservices
从以上微服务的定义和特征中还可以明显地感觉到,微服务追求的是更加自由的架构风格,摒弃了几乎所有SOA中可以抛弃的约束和规定,提倡以“实践标准”代替“规范标准”。**可是,如果没有了统一的规范和约束,以前SOA所解决的那些分布式服务的问题,不也就一下子都重新都出现了吗?**的确如此,服务的注册发现、跟踪治理、负载均衡、故障隔离、认证授权、伸缩扩展、传输通讯、事务处理,等等,这些问题,微服务中不再会有统一的解决方案,即使只讨论Java范围内会使用到的微服务,光一个服务间通讯问题,可以列入解决方案的候选清单的就有:RMI(Sun/Oracle)、Thrift(Facebook)、gRPC(Google)、Motan2(新浪)、Finagle(Twitter)、Arvo(Hadoop)、JSON-RPC、REST,等等;光一个服务发现问题,可以选择的就有:Eureka(Netflix)、Consul(HashiCorp)、Zookeeper(Apache)、Etcd(CoreOS)、CoreDNS(CNCF),等等。其他领域的情况也是与此类似,总之,完全是八仙过海,各显神通的局面。
微服务所带来的自由是一把双刃开锋的宝剑,当软件架构者拿起这把宝剑,一刃指向SOA定下的复杂技术标准,将选择的权力夺回的同一时刻,另外一刃也正朝向着自己映出冷冷的寒光。微服务时代中,软件研发本身的复杂度应该说是有所降低,一个简单服务,并不见得就会同时面临分布式中所有的问题,也就没有必要背上SOA那百宝袋般沉重的技术包袱。需要解决什么问题,就引入什么工具;团队熟悉什么技术,就使用什么框架。此外,像Spring Cloud这样的胶水式的全家桶工具集,通过一致的接口、声明和配置,进一步屏蔽了源自于具体工具、框架的复杂性,降低了在不同工具、框架之间切换的成本,所以,作为一个普通的服务开发者,作为一个“螺丝钉”式的程序员,微服务架构是友善的。可是,微服务对架构者是满满的恶意,对架构能力要求已提升到史无前例的程度,笔者在这部文档的多处反复强调过,技术架构者的第一职责就是做决策权衡,有利有弊才需要决策,有取有舍才需要权衡,如果架构者本身的知识面不足以覆盖所需要决策的内容,不清楚其中利弊,恐怕也就无可避免地陷入选择困难症的困境之中。
微服务时代充满着自由的气息,微服务时代充斥着迷茫的选择。软件架构不会止步于自由,微服务仍不是架构探索终点,如果有下一个时代,我希望是信息系统能同时拥有微服务的自由权利,围绕业务能力构建自己的服务而不受技术规范管束,但同时又不必以承担自行解决分布式的问题的责任为代价。管他什么利弊权衡!小孩子才做选择题,成年人全部都要!
在微服务架构中,会面临一些必须解决的问题,比如注册发现、跟踪治理、负载均衡、传输通讯等。但这些问题在原始分布式时代就一直存在。最常见的解决方法是怎样的:
在微服务时代,我们之所以不得不在应用服务层面,而不是基础设施层面去解决这些分布式问题,完全是因为由硬件构成的基础设施,跟不上由软件构成的应用服务的灵活性。
注册发现、跟踪治理等等问题的解决,依靠的就是虚拟化技术和容器化技术。微服务时代所取得的成就,本身就离不开以Docker为代表的早期容器化技术的巨大贡献。
早期的容器只是被简单地视为一种可快速启动的服务运行环境,使用它的目的是方便程序的分发部署。所以,早期阶段针对单个服务的容器,并没有真正参与到分布式问题的解决之中。
2017 年,可以说是容器生态发展历史中具有里程碑意义的一年。
Docker Swarm、Apache Mesos、与Kubernates是“容器战争”的主要竞争者。Kubernetes 最后从众多的容器管理系统中脱颖而出、“登基加冕”,就代表了容器发展中一个时代的结束。而且我可以说,它带来的容器间网络、服务、负载均衡、配置等虚拟化基础设施,也将会是开启下一个软件架构发展新纪元的钥匙。
针对同一个分布式服务的问题,对比下Spring Cloud中提供的应用层的解决方案,以及Kubernetes中提供的基础设施层面的解决方案。虽然Spring Cloud和Kubernetes的出发点不同,解决问题的方法和效果也不一样,但Kubernetes的确提供了一条全新的、前途更加广阔的解题思路。
当虚拟化的基础设施,开始从单个服务的容器发展到由多个容器构成的服务集群,以及集群所需的所有通讯、存储设施的时候,软件与硬件的界限就开始模糊了。
一旦硬件能够跟得上软件的灵活性,那么这些与业务无关的技术问题,便很可能从软件的层面剥离出来,在硬件的基础设施之内就被悄悄解决掉,让软件可以只专注于业务,真正“围绕业务能力构建”团队与产品。那么原来只能从软件层面解决的分布式架构问题,于是有了另外一种解法:应用代码与基础设施软硬一体,合力应对。
我们借此就来到了现在媒体文章中常说的“云原生”时代。
Kubernetes 成为了容器战争的胜利者,标志着后微服务时代的开端,但 Kubernetes 其实并没有完美地解决全部的分布式问题。
仅从功能灵活强大这点来看,Kubernetes 反而还不如之前的 Spring Cloud 方案。这是因为有一些问题处于应用系统与基础设施的边缘,我们很难能完全在基础设施的层面中,去精细化地解决掉它们。
举个例子,微服务A调用了微服务B中发布的两个服务,我们称之为B1和B2,假设B1表现正常,但B2出现了持续的500错误,那大道一定的阈值之后,我们就应该对B2进行熔断,以避免产生雪崩效应。
这种问题在通过Spring Cloud这类应用代码实现的微服务中,其实并不难处理,反正是使用代码(或者配置)来解决问题,只要合乎逻辑,做什么功能均可,只是会受限于开发人员的想象力与技术能力。但基础设施是针对整个容器来做整体管理的,它的力度就相对粗犷。实际上,类似的情况不仅仅会在断路器上出现,服务的监控、认证、授权、安全、负载均衡等功能,都有细化管理的需求。比如,服务调用时的负载均衡,往往需要根据流量特征,调整负载均衡的层次、算法等,而DNS尽管能实现一定程度的负载均衡,但它通常并不能满足这些额外的需求。
为了解决这一类问题,微服务基础设施很快就进行了第二次进化,引入在今天被我们叫做是“服务网格”(Service Mesh)的“边车代理模式”(Sidecar Proxy)。
具体到咱们现在的语境里,“边车”的意思是,微服务基础设施会由系统自动地在服务的资源容器(指 Kubernetes 的 Pod)中注入一个通讯代理服务器(相当于那个挎斗),用类似网络安全里中间人攻击的方式进行流量劫持,在应用毫无感知的情况下,悄悄接管掉应用的所有对外通讯。
这个代理除了会实现正常的服务调用以外(称为数据平面通讯),同时还接受来自控制器的指令(称为控制平面通讯),根据控制平面中的配置,分析数据平面通讯的内容,以实现熔断、认证、度量、监控、负载均衡等各种附加功能。
这样,就实现了既不需要在应用层面附带额外的代码,也提供了几乎不亚于应用代码的精细管理能力的目的。
虽然,我们很难从概念上,来判定一个与应用系统运行于同一资源容器之内的代理服务,到底应该算是软件,还是算作基础设施,但只要它对应用是透明的,不需要改动任何软件代码就可以实现服务治理,这就足够了。
最后再谈谈近一两年才兴起的“无服务架构”。在工业界,2012 年,iron.io 公司率先提出了“无服务”(Serverless,应该翻译为“无服务器”才合适,但现在用“无服务”已形成习惯了)的概念;2014 年开始,AWS 发布了命名为 Lambda 的商业化无服务应用,并在后续的几年里逐步得到了开发者的认可,发展成目前世界上最大的无服务的运行平台;到了 2019 年,中国的阿里云、腾讯云等厂商,也发布了无服务的产品。“无服务”成了近期技术圈里的“新网红”之一。
无服务架构演进背景也是前面所讲的经历了多个阶段不断演进的。计算机发展也经历了大型机、小型机、PC 机、虚拟机和云服务器(大多数云服务器也是虚拟机)
在云计算时代,云服务厂商提供 IaaS、PaaS、SaaS 能力,实现从硬件到软件的免托管和开箱即用的能力。
无服务架构不像微服务架构、SOA架构那么复杂,它最大的特点就是简单。只涉及后端设施(Backend)和函数(Function)两块内容。
后端设施是指数据库、消息队列、日志、存储,等等这一类用于支撑业务逻辑运行,但本身无业务含义的技术组件,这些后端设施都运行在云中,无服务中称其为“后端即服务”(Backend as a Service,BaaS)。
函数是指业务逻辑代码,这里函数的概念与粒度,都已经很接近于程序编码角度的函数了,其区别是无服务中的函数运行在云端,不必考虑算力问题,不必考虑容量规划(从技术角度可以不考虑,从计费的角度你的钱包够不够用还是要掂量一下的),无服务中称其为“函数即服务”(Function as a Service,FaaS)。
无服务的愿景是让开发者只需要纯粹地关注业务。
与单体架构、微服务架构不同,无服务架构天生的一些特点,比如冷启动、无状态、运行时间有限制等等,决定了它不是一种具有普适性的架构模式。
如果微服务架构是分布式系统这条路当前所能做到的极致,那么无服务架构,也许就是“不分布式”的云端系统这条路的起点。
We can only see a short distance ahead, but we can see plenty there that needs to be done.
– Alan Mathison Turing,Computing Machinery and Intelligence,1950
吾等目力短亦浅,能见百事待践行。
– 图灵,《计算机器与智能》,1950
无服务架构之IaaS、PaaS、SaaS定义如下,
把计算基础(服务器、网络技术、存储和数据中心空间)作为一项服务提供给客户。它也包括提供操作系统和虚拟化技术、来管理资源。消费者通过 Internet 可以从完善的计算机基础设施获得服务。
优点:
平台即服务提供商将硬件和软件托管在自己的基础架构上,并通过互联网连接以集成解决方案、解决方案堆栈或服务的形式将该平台交付给用户。
PaaS 主要面向开发人员和程序员,它允许用户开发、运行和管理自己的应用,而无需构建和维护通常与该流程相关联的基础架构。
开发人员只需编写代码、构建和管理应用,不再有软件更新或硬件维护方面的麻烦。系统将会提供构建和部署环境。
优点:
软件即服务提供了一种完善的产品,其运行和管理皆由服务提供商负责。人们通常所说的软件即服务指的是终端用户应用程序。使用 SaaS 产品时,服务的维护和底层基础设施的管理都不用用户操心,用户只需要考虑怎样使用 SaaS 软件就可以了。
优点:
三者之间的区别