在于马萨诸塞州的波士顿举办的O’Reilly架构大会上,Rags Srinivas对Matt Stine进行了一次采访。Matt在采访中谈论了Cloud Native架构以及它在文化和技术方面的某些挑战,他也提到了NetFlix的某些服务,以及如何通过Spring对其进行封装,在这个平台上进行微服务的架构设计与开发。他还谈到了SOA,以及其中可能缺失的一些概念。
InfoQ:你们好,欢迎来到这里。在我身边的是来自Pivotal的Matt Stine,我们现在正处于在马萨诸塞州的波士顿举办的O’Reilly软件架构大会的现场。那么Matt,如果你能够为InfoQ的读者们介绍一下你自己的话,那就再好不过了。
Matt :当然了。是的,正如你所说,我是Matt Stine。我来自于Pivotal,自从几年之前Pivotal成立以来,我就以某种形式参与了Cloud Foundry团队的工作。我的工作职责很多:工程师、技术传道士、还要管理一些技术市场工作以及撰写博客。最近,我要负责一些为Cloud Foundry开发的一系列服务的产品管理工作,包括Spring Cloud和Netflix OSS。
InfoQ:我知道你最近编写的一本书刚刚由O’Reilly出版,并且在这次大会中发放给与会者,内容是有关于cloud native架构的。从架构师或开发者的观点来看,cloud native这种架构到底有什么意义,能举几个例子吗?
Matt :我所称之为“cloud native”的这个概念是多种不同思想的一个集合,这些思想与许多公司正在转移到云平台的趋势是一致的。这些思想包括DevOps、持续交付、微服务、敏捷基础设施、康威定律,以及根据商业能力对公司进行重组。这里面包括了许多东西,cloud native是一种我与其他一些人约定俗成的名称。如果说这本书能够为读者带来什么,可以说我在书中所说的主体是关于人、组织结构以及文化的变革的。其中也稍微提到了一些技术方面的内容。
虽然本书的主题是cloud native架构,但书中的内容都是与人有关的话题,这看上去有些奇怪。但事实上,为了让这种架构发挥其作用,必须对你的公司进行变革,以促进它的功效。一旦你实现了公司的重组,这个架构就会为你带来很大的利益。因此重点在于这一趋势并不仅仅是一种技术趋势,甚至可以说它的重点并不在技术上面,而更多的是一种文化与组织结构变革的趋势。
InfoQ:好的,你的回答为接下来的问题进行了很好的铺垫。微服务从本质上来说是一种全新的概念吗?还是说它其实就是SOA,只是旧瓶装新酒而已?
Matt :我曾经也参与过关于微服务与SOA之间的关联的这种讨论。在某种程度上,我觉得这种讨论的意义不大。这么说吧,如果我们比较一下SOA在维基百科介绍中的前几个段落,那么在我们如今称之为微服务的概念中确实有许多方面与SOA是非常相近的。我认为真正的区别在于供应商是如何实现SOA的,他们所专注的是将所有东西都扔到一个新的中间件中,称其为企业服务总线(Enterprise Service Bus - ESB),让它来取代所有其它所有大型的中间件,因为那些中间件听起来不够酷,已经无法成为服务的卖点了。我不是说ESB是一种糟糕的技术,而是说我们使用的方式不对,只是用一个新的一体性架构去取代现有的一体性架构,这种方式只是把复杂性从一端转移到另一端而已。要想转变为一种更加面向服务的架构,以上这些做法都是不必要的。
看一看服务的基本原则,一个清晰的专注点,一个清晰的契约以及一个清晰的API。换句话说,SOA背后的原则在本质上与微服务背后的技术原则在概念上是趋向于一致的。而在SOA这个趋势中,你所忽视的东西是对文化、组织、甚至运维方面的问题的强调。
我一直在考虑运维的问题,而当我听到Neal Ford关于微服务的演讲时,这一想法终于清晰地展现在我眼前。他在演讲中表示:当他看到在架构图中包含了ESB时,这些架构图看起来很不错,也容易理解,但从运维的角度来看,它们实际上什么都没做。
然后我们继续前进,在这个基础上实施持续交付。这期间我们遭遇了无数的意外情况,因为没人考虑过这种架构运行在生产环境时会发生什么情况。之后我们将目光投向了微服务,它是在DevOps与持续交付这些概念出现后第一批浮现出的架构选择之一。现在我们有了一个个团队,在他们的工作内容的背后是这些概念在支撑着他们的思想,然后这种特殊类型的架构就突然间出现了。对于这些新型架构,我们现在只是为它们打上了一个“微服务”的标签。
因此我认为,从原则上来说,这两者这间没有太大的差别,但从实现的角度来说,这两者之间存存在着巨大的差异。我想这也是关于微服务与SOA之间的异同点的讨论会出现的原因之一。从SOA和微服务的基本原则以及背后的历史来考虑,它们没有多大的差别。但在实现微服务与SOA的过程中,从参与者每天的工作内容来看,这两者是完全不同的。
InfoQ:在SOA方面,一个经典的失败案例是一体性的UDDI。不知道你是否还记得它,也就是统一描述、发现和集成?即使从微服务的角度来看,服务发现也仍然是十分关键的,是吗?
Matt :没错。
InfoQ:那么在微服务的世界,它的重要性到底怎样,具体又发生了些什么?
Matt :是的,感谢你事先已经将问题发给我看过了,我也因此重新看了一遍UDDI,让我想起它代表什么含义了。在它流行的年代中,我其实从来没有使用过它。当然,我也不清楚它到底算不算是流行过,但至少当时人们确实在谈论它。我想我们如今所说的服务发现和当时已经有了很大的不同。就我对UDDI的理解来看,它很像一本电话簿,我作为某个服务的开发者打开了这本电话簿,以寻找我所需的某些东西,例如某个处理信用卡的服务。
我首先会提出的第一个问题是:“那么,这里面有哪些可用的信用卡处理服务呢?”根据UDDI的回答,我会选择一种服务。在选择了该服务之后,我会进行查看该服务的契约定义,也就是某些WSDL文档。随后我就选择了这种WSDL,很可能会根据这个WSDL生成一些代码,通过它与这个信用卡处理服务进行交互。
最终你可能会产生某种幻觉,即通过目录提供的这些服务是一种松耦合的架构方式,但实际上你又与那个WSDL中所定义的特定契约产生了紧耦合。一旦WSDL产生了变化,你所生成的代码在一瞬间将失去作用,你将不断地在这个循环中无法自拨。
因此,我认为对如今的服务发现来看,它仍然具有目录这一思想,但它的目的不是告诉让我们查看“其中有”哪些服务。而是表现为我们知道需要某些服务,并且知道在架构中存在着这种服务,而且这种服务有一个逻辑名称。我只需要知道如何将这个逻辑名称转换为实际的网络地址,并通过该地址与服务进行通信。
因此在这个情况下我所编写的典型代码是这样的:我在创建一个存储服务和一个客户服务,并且我知道该客户服务需要调用这个存储服务,只是还不知道这个存储服务的实际地址。我不想对这个地址进行硬编码,因为这会造成对这些服务的紧耦合。通过使用一种服务注册表,我就可以对从哪里获取这个组件的信息解耦。通过这种设计,我就能够随意地对这个存储服务进行各种操作:可以对它进行横向扩展、或者紧缩,也可以把它转移到其它地方(因为我有时希望使用云架构)。即使如此,也不会破坏运行中的客户服务。
此外,我们也将对该服务契约的发现与服务注册表本身进行了完全解耦。你可以看看Netflix的Eureka,在其中你找不到任何WSDL或规格说明,以告诉你它使用的API是什么样的。你只是获得某个服务的地址并进行连接,它会告诉你“我的API在这里”,或者你也可以通过其它某些方法获得它的API信息。但发现过程与API是两种相互独立的关注点,并且已经被我们拆分了。而在UDDI中,这两者之间具有更强的耦合性。
再重申一下,如果从很高的层次来思考,就像思考SOA与微服务的区别一样,那么在服务发现与UDDI之间确实存在着某些类似之处,但它们的实现方式是完全不同的。
InfoQ:我想你刚刚提到了Netflix的一些微服务,我知道你目前参与了Spring Cloud的工作,对吧?那么能否请你大体上谈一谈Netflix OSS与Spring Cloud之间的共同效应,以及一些你所特别关注的组件?
Matt :Pivotal与 Netflix之间的关系越来越接近,并且还在不断发展,尤其是在Sprint团队与Netflix之间,但Pivotal的其他服务也在增进与Netflix的关系。Netflix长期以来一直都在使用Spring技术,他们已经成为了Spring Boot的一个重要的支持者和用户,在Netflix中有大量的应用都是使用Spring Boot编写的。在Spring Boot诞生之前,他们也是Grails的重度用户。
在创建Spring Cloud时,Spring与Netflix的工程团队之间进行了多次交流,以更好地了解服务的工作方式以及如何正确地使用它们。我们所做的不是随便找一种开源实现,对其进行一下简单封装就丢给他们那么简单。为了确保出色地完成这个产品,我们之间进行了大量的合作。我们还将继续进行更深入的交流,包括Spring的下一代产品和Netflix在云技术方面的下一代产品将如何实现,并让它们联系更紧密。因此,我期待着在今后的几个月和几年中,这两个团队的相互交流能够带来更令人激动的产品。
InfoQ:好的。从一个开发者的角度来看,要做的事情确实很多。我的意思是,开发者要使用服务发现,当然还有很多常见的任务 —— 要扩展至大规模,要连接日志记录等等,对吗?
Matt :没错。
InfoQ:显然,像Cloud Foundry这样的PaaS能够帮助开发者,对吗?能够请你再详细地阐述一下,微服务方式与PaaS方式,或至少说Cloud Foundry方式有哪些相似之处,或者说它们并不相似?
Matt :回想9个月以前,当时我们还完全没有考虑到这些问题。当时才刚刚有了微服务的思想,还处于发展的初期。当时还有一些关于Cloud Foundry的讨论:从开发者的生产力、运维上的效率以及提高质量来看,它意味着什么?当时我们的想法是通过它将那些遗留代码搬迁到云端。这里面有很多问题,实现这一目标非常困难,甚至是不可能的,因此在大多数情况下你是不会这么做的。
然后这些问题就来了:“好吧,那么为在Cloud Foundry上运行而开发的应用程序看起来是怎样的呢?”然后我开始认真思考这个问题,你怎样回答呢?当时,我们的答案是十二要素(Twelve Factor),这是由Heroku所提出的宣言。我们开始在Cloud Foundry中使用了其中提到的buildpack模型,十二要素非常适合于Cloud Foundry,你甚至可以说Cloud Foundry是专用于运行十二要素应用的平台。但即使你或许能从中得到某些如何让应用正确运行的实现细节,但如果你说“我打算设计一种能够正确运行的应用”,然后我们表示你可以创建一个大规模的十二因素应用。这真是我们的目标吗?应该不是。
因此我开始把目光转向微服务。在Cloud Foundry与微服务之间存在着一种协同性,甚至是共生性。使用微服务时,你必须处理许多运维方面的挑战。事实证明,Cloud Foundry所要应对的运维挑战也是完全一样的。回头看看Cloud Foundry:有一些应用在上面运行得挺好,有一些则不然。再看看微服务通常是怎样创建的,从Cloud Foundry的角度来看,它们的创建方式几乎是一致的。
这两者之间并没有依赖关系,但如果能够将它们连结在一起,将会产生一种强大的协同作用。为此,我发起了这次讨论。在上一次Cloud Foundry Summit大会上,我提出了一个演讲主题:“Cloud Foundry与微服务:一种共生关系。”这个提议得到了批准,并由我负责演讲。在之后的几个月之内,这个观念得到了人们的接受和应用,最终使我们完全投入到这个讨论中。
同时,Spring Cloud项目的开展与这一讨论并没有什么关系,而最终我们让这两个小组坐到了一起。我们现在可以全力打造Cloud Foundry、微服务、Spring Cloud和Netflix。我们的目标是创建一种cloud native应用平台和开发框架,创建一种全栈的解决方案,用于打造架构、管理(至少从技术角度来看)你需要处理的一切。余下的东西就是我们无法通过技术解决的问题:文化与组织结构方面的挑战。
InfoQ:如今整个产业都在为容器技术疯狂,是吗?你能否描述一下Spring Boot的特征?我会将Spring视为一种轻量级容器,但我不确定Spring Boot是否是一种轻量级容器。另外,你对于容器的一般性看法是怎样的?
Matt :当我们在谈论容器的时候,我们其实经常是在谈论Linux容器,我假设你所说的容器是指Java容器。不幸的是,容器这个术语承载了太多内容。不管怎样,大家都在谈论Docker。那么Docker和Spring Boot之间有什么关系呢?
创建一种符合Boot应用规范的Spring应用非常简单。Boot帮我封装了用于运行web应用的servlet容器,我可以在Tomcat、Jetty或Undertow之间进行任意选择。
现在我有了一个自包含的JAR文件,它能够完成我所需的一切功能。我能够轻易地将该文件加载到某个安装了Java的Docker容器镜像文件中,然后创建一个新的层,以加载Spring Boot应用。现在我有了一个可移植的容器镜像,其中包含了可进行发布的Spring Boot应用。这是一种非常良好的协作效应。很快你就能够通过Cloud Foundry或Lattice在Diego上运行Docker或Rocket(或其它什么)镜像了,这套方案为你提供了非常强大的工具。
从持续交付的角度来看,我在笔记本电脑上所运行的应用,通过持续集成管道所发布的应用,以及在Cloud Foundry上的生产环境上所运行的应用是完全一致的,这是一种非常理想的场景。持续交付的一个核心原则是差异的决定性,哪怕一个很小的差异也可能会造成在某个环境下运行良好的应用,换了一个环境就无法运行了。因为我清楚地知道,我所开发的、测试的、以及在生产环境中运行的应用在文件系统级别上是完全相同的,因此我对应用能够正常运行很有信心。
关键的不同点显然在于不同的环境中运行着不同的核心,它们应当是完全相同,或是非常接近的。但这一点应当是唯一的不同之处了,在几年之前,我们还无法轻易地实现这一点,甚至要接近实现这一点也是非常困难的。我们可以通过虚拟机来模拟这一点,但它们的价格相对高昂,并且启动与调整时间也很长。而如今在容器中只需几秒钟就可以完成这一切。
不过现在你还有许多问题需要处理。你如何进行水平扩展?你如何管理这些镜像的创建与更新?如果你不能很好地管理容器镜像的维护,让它们继承于某个通用的根镜像(这种做法比较合理),那么你就会创建出大量的镜像,而它们之间无法共享内容。你会很快地填满整个硬盘,并且产生效率低下的问题。这些技术看上去很简单,但别被这种简单性所迷惑了。我可以在五分钟之内就创建好一个容器镜像并让它运行起来,这只不过是一个开始练习而已。随着你逐渐地增加规模,有许多工作需要靠整个团队的纪律流程进行规范,并且需要通过一系列工具负责创建与管理这些镜像文件,让它们保持一致性与可重复性。因此如果有多个团队在开发应用,这些团队不需要各自定制一套根文件系统,我们也可以从容器镜像带给我们的效率中受益。
我想说的是,天下没有免费的午餐。这些工具都十分强大,但都不是可以轻易掌握的。为了有效地利用它们,你不仅要学习它们的使用,同时也要改变你的某些工作方式。
InfoQ:InfoQ的读者们有许多实践者和架构师,他们在敏捷方面有着大量的实践经验。我们从敏捷开始,那么这是我们今天最后一个问题了。从架构的角度来看,敏捷是否有意义?有时人们的说法是持续改进以及实施敏捷,对吧?那么架构与敏捷如何相互融合呢?
Matt :我有一种感觉:由于在敏捷方法中存在着一些仪式,而这些仪式有时会掩盖了敏捷的核心思想,就是迭代式地对反馈进行回应。我们不需要过度的计划,不需要过度的设计,也不需要过度的架构。我们已经看到了这一点,但如果我们稍不留意,就会从光谱的一边跑到相反的另一边。在这一边的做法是繁重的前期计划与设计,或者说瀑布模型或其它任何名称。而另一边的做法是完全不考虑任何东西、不进行任何设计、不进行任何头脑风暴,只是沿着车轮前进,不断踩下油门,前进、前进、前进,编码、编码、编码,测试、测试、测试……我们天真地相信这种方式最终会带来良好的结果。这两种极端都不是正确的方式。
几年之前,Rich Hickey的一次讲座激怒了许多人(可以在Info上找到这个链接:http://www.infoq.com/presentations/Simple-Made-Easy)。在演讲中的某个部分,他将测试驱动开发比喻为“护栏驱动开发”。他说:“我在开车时不会不停地撞击马路两边的护栏,并期望这些护栏能够让我保持在正道上。”很多人因此觉得他表示的意思是测试驱动开发是一种糟糕的或愚蠢的实践,“你不应当这么做,你不该采用TDD” 。我在这里不是要为Rich开脱,但我不认为这是他的真实想法。我想他要表示的是你仍然有可以思考的余地。实际上,思考确实是至关重要的。思考如何架构、思考如何设计、思考你的前进方向,然后将TDD等实践作为一种工具以帮助你达到目的地。
因此我们可以停下编写测试与代码的工作,想一想我们的前进方向是什么?这个模块与API看起来应该是怎样的?我们所需要处理的关注点是什么,到底是难以为它编写测试,还是说我们根本不知道要为什么编写测试?所以我们或许应当退一步,找一个房间,挂起一块白板,把一切设计都画在上面。但我们不是要将这些图形转变为重量级的正规UML文档,进行轻量级的架构与设计是完全有可能的,但首先你要意识到,在开始动手敲键盘之前,工作应当已经在你的头脑中进行了。
我想,如果你在这条光谱中为你的团队找到了适当的位置,那么你也将找到成功之路。而这个位置很大程度上取决于你所试图创建的功能。它的内在复杂性是什么?如果你只是要创建一个相对较小的应用,那么你或许不需要进行那么多架构工作。但要创建某种由微服务组成的大型分布式系统,以“web规模”运行,并打算支持几百万用户。好吧,那么只是使用TDD应该是不行的。
因此,就像软件工程中的所有问题一样,对这个问题也不存在一种二元的回答,它不是非此即彼的。在这两个极端之间必定存在着某个适合你团队的正确答案,你必须把问题放到你所试图解决的问题上下文中以找到答案,也就是你需要多少架构实践、以及多少文档工作才能最终实现你的目标。如果你能够退一步,将敏捷当作某种保持反馈循环运作的手段,即获取反馈、对它进行回应、进行方向修正、并打造正确的产品,那么剩余的部分会自动朝着正确的方向前进。
只要将持续改进、持续反馈以及持续对反馈进行回应作为工作中的核心思想,那你就可以随意选择如何进行架构设计,也可以选择结对编程和TDD。你可以随意选择任何实践,并且发现适合你现状的平衡点是什么。
Matt Stine 是 Pivotal的一位技术产品经理。他是一位具有15年企业级IT产业经验的老手,项目经验涵盖了多种业务领域。他也是O'Reilly最近出版的 《Migrating to Cloud-Native Application Architectures》 一书的作者,可以免费下载这本电子书。
查看英文原文: Cloud Native Architectures - a Conversation with Matt Stine