【IT168 技术文章】
概述
爱因斯坦在很多年前做了上述的著名论断,到如今,这句话依然与大型软件系统的构建息息相关。不幸的是,任何一个从事IT业足够长时间的人都能够指出,有太多的软件系统已经在爱因斯坦的这句话上失败了。一些系统做的太简单而不能胜任其应有的性能;而另一些系统则做的过于复杂,使的开发和维护的成本急剧上升,更不用说不同系统整合变得也几乎不可能了。看上去要达到"简要"这个程度更像是一个不切实际的梦想。我们到底错在里呢?
松耦合
我们没有必要去很远的地方去寻找这种问题,其实它就在我们身边。当我们构建了越来越多的软件系统后,许多相似的场景和模式出现了。很自然的,我们更希望能重复利用这些现有系统的功能,而不是再从头去构建它们。在这里,我们先给出一个名词的定义“真实依赖”,它代表了一个系统依赖另一个系统提供的功能的一种状态。如果这个世界只存在“真实依赖”,那么爱因斯坦的预言也许在多年以前已经实现的很好了。问题就在于有真实依赖同时,我们同样创建了“虚假依赖”。
如果你去海外出差,你知道你必须随身带着电源适配器,否则你的生活将一塌糊涂。在这里,“真实依赖”是你需要电源,而“虚假依赖”是你的插头必须能够插到当地的插座去。看看那些不同国家的各色的插头,你会注意到,它们有些又小又紧凑,而有些则又大又粗。
在这里给我们的教训就是,“虚假依赖”是不可以移除的,但是我们可以削弱它。如果我们能够理想的把系统间的依赖降到最低,那么就已经达到了松耦合的目的。我们可以把爱因斯坦那句注明理论改为:“虚假依赖应该降到最低,而真实依赖是不可改变的。”
SOA的定义和解释
现在,我们可以给面向服务架构下一个定义了。SOA是个旨在使相互作用的软件业务达到松耦合效果的架构。服务是一个由服务提供者提供的,实现服务消费者请求的业务单元。提供者和消费者都是软件代理为了各自的利益而产生的角色。
这听起来有些太抽象了,但SOA实际上无所不在。让我们来看一个在我们生活中随处可见的有关SOA的例子吧。以CD做例子。如果你想播放CD,你会把CD插到一个CD播放器里面,CD播放器来为你播放。在这里,CD播放器提供了播放CD的服务。令人高兴的是,你可以更换不同的CD播放器。你可以用一个随身的播放器或是你的昂贵的立体声系统来播放同一张CD。它们都给您提供了播放CD的服务,但是服务质量是不同的。
SOA的思想与面向对象思想有着很大的差异。在面向对象编程中,数据和行为被强烈的建议绑定在一起.因此。因此,在面向对象的设计思想中,每个CD应该有它自己的播放器,并且不应该被分开。这听起来有些可笑,但这确实是我们构建许多软件系统所用的方法。
服务的结果通常可以改变消费者的状态同样也可能改变服务提供商的状态,或者也可能都改变。在听完用你的CD播放器播完的音乐后,可以说你的心情发生了变化,从“沮丧”变成了“愉快”。如果你想要一个涉及到双方状态都改变的例子,那么在饭店吃饭将是个很好的例子。
通常我们找人做某项工作是因为那个人是这方面的专家。而消费一个服务通常要比我们自己干来的更便宜和高效。我们大部分的人都能意识到我们不可能成为每个领域的专家。这个道理同样适用于构建软件系统,我们称之为“关注分离”。这已经被认为是软件工程的一条基本原理。
SOA是如何达到使交互的软件代理松耦合的目的呢?它通过满足以下两条结构约束来实现:
1.对参与的软件代理来说,是简单并且普遍存在的接口的小集合。只有通用的语义能够在这些接口里编码,而这些接口对所有的提供者和消费者都是全局可用的。
2.接口间传递的消息必须是可描述的并通过扩展方式传递。没有或者只有极少量的系统行为被消息订阅。样式约束了消息的词汇和结构。扩展的样式允许新版的服务在无需打破原有服务的情况下被使用。
正如上面的电源适配器的例子所说的,接口非常的重要。如果接口不工作,那么整个系统也将瘫痪。在分布式系统中,接口则是即昂贵又易于出错的。接口需要指示系统的行为,而在不同的平台与语言之间要实现接口是非常困难的。远程接口同样也是在大部分的分布式系统中最慢的一种。为所有的应用程序创建一些可重用的接口来代替为每个应用程序创建新的接口则显的尤为重要。
因为我们只拥有很少一部分可通用接口,我们必须在消息中表示应用程序特定的语义。我们可以通过我们的接口发送任何消息,但是在我们说某个架构是面向服务的之前,我们必须遵循一些规则。
第一,这个消息必须是可描述的,因为服务提供者有责任解决问题。这就好比你来到一个饭馆,告诉服务员你要点的菜单和所喜爱的口味,但是你不会手把手的告诉他们的厨师怎么来做你要吃的鱼。
第二,如果你的消息没有按照一定的格式、结构来书写,服务提供者将不能理解你的请求。限制了词汇和结构的消息对于任何一次高效的交流都是必须的。消息受限的地方越多,则这个消息将越容易被理解,虽然这需要通过牺牲扩展性来达到目的。
第三,扩展性极其的重要。要理解这一点并不难。这个世界是个在不断变化的世界,此道理同样存在于软件系统所处的各个环境。这些变化要求软件系统进行相应的变化,包括服务消费者,提供者,还有他们相互交流的消息。如果消息是不可扩展的,消费者和提供者将都受限于某个特定的服务版本。尽管扩展性如此的重要,不过在以往的情况,依然容易被忽略。最好的情况也只是,它(扩展性)被简单的认为是种好的模式而不是基础。约束和扩展性是一对深深的矛盾体,但是两者又都需要。你提升了任何一方都将以削弱另一方为代价,最好的方法是能够在两者之间寻找到一个合适的平衡点。
第四,一个SOA必须拥有一个机制,它能使消费者在其寻找到的一个服务的上下文环境下发现一个服务提供者。这个机制应当非常的可变,并且不是必须拥有一个中央注册处。
额外的约束
在SOA中,有几项额外的约束用于提高其可测性、性能及可靠性。
无状态服务
每个消费者发送给提供者的消息必须包含所有提供者处理该请求所需要的信息。此约束使的提供者更加的可测,因为提供者不需要在请求之间保存状态信息。既然每个请求都被通用的对待,这就形成了有效的“服务批量生产”。同样可以称此约束提高了可见度,因为任何一个监控软件都可以监控单个的请求并指出其目的。由于不需要担心中间状态,因此从部分的失败中恢复也是相对简单的。这使的服务更加可靠。
有状态服务
有状态服务在许多场景下很难避免。其中一个便是在消费者和提供者间建立一个会话。会话是典型的为了性能而建立的。例如,为每个请求发送安全证书对消费者和提供者来说都是相当沉重的负担,如果把安全证书替换成在消费者和提供者之间共享的一种标记,那么会快上许多。另一个场景那就是给消费者提供服务。
有状态服务要求消费者和提供者都共享同一特定消费者的上下文,它可能被提供者和消费者间交互的消息所包含或引用。此约束的缺点是,它可能全面降低服务提供者的可测性,因为提供者可能需要为每个消费者记忆共享的上下文。它同样还增加了服务提供者与消费者间的耦合关系,使的服务的筛选变的更加的困难。
幂数请求
由一个软件代理接收到的重复请求与单个的请求拥有相同的效果。此约束允许提供者和消费者通过简单的进行“如果请求失败则重复执行”来全面提高服务的可靠性。
源于SOA的Web服务
每个人都大概的了解什么是“web服务”,但是并没有一个可被广泛接受的定义。web服务的定义同时也被W3C Web服务框架工作组激烈的讨论。尽管定义一个web服务是如此的困难,但是大致说来满足下列约束的web服务就是一个SOA:
1.接口必须是基于互联网协议,例如HTTP、FTP和SMTP。
2.除非是二进制附件,消息必须是XML格式。
有两个重要的Web服务格式,分别是:SOAP Web服务和REST Web服务。
SOAP Web 服务
对于SOAP Web服务,介绍下面的约束:
1.除了二进制附件,消息必须由SOAP传输。
2.服务的描述必须是用WSDL(Web Services Description Language),即描述服务的标准语言。
SOAP Web服务是一种在企业中最具有共同市场的网络服务形式。一些人简单的将web service和SOAP、WSDL services混淆。SOAP规范定义了结构化信息,依据SOAP 1.2 规范,此信息能够在很多底层协议下交换。换句话说,SOAP就如一个带有本身内容的信封。SOAP的一个优点是它允许有多种信息交换形式来传送且固化信息的联系,这不同于传统的请求/响应形式。SOAP Web服务有方面的内容,SOAP RPC和document-centric SOAP web services。SOAP RPC web服务不是SOA,而document-centric SOAP web 服务是SOA。
SOAP RPC Web 服务
SOAP RPC Web 服务打破了由SOA需要的第二个约束。SOAP RPC Web 服务将SOAP消息编码为RPC(远程过程调用)。换句话说,SOAP RPC通过底层的一个通用接口“进入”了新的特定的RPC应用接口。它(SOAP RPC)有效的指示系统行为和应用语义。因为系统行为在分布式环境下是很难被指示的,由SOAP RPC创建的应用很自然的不是共同操作的。许多实际中的程序运行已经证实了这一点。
面对此困难,WS-I basic profile(Web服务互用性组织)和SOAP 1.2已经对RPC的随意性做了支持。RPC也趋向于命令性而非描述性,这违背SOA的本质。可笑的是,SOAP最初是为RPC而设计的。有些人认为在不久的将来,“SOAP”将实际代表“SOA协议”。
REST Web 服务
术语 “REST”首先是由Roy Fielding用来描述网络架构的。REST Web 服务是SOA所基于的“资源”的概念。一个资源就拥有一个URI。一个资源可能没有或有更多的代表性。通常,如果一种资源没有代表性可得到,我们就说这种资源不存在。REST Web 服务需要下面的额外约束:
1.接口仅限于HTTP。下面的语义是被定义的:
HTTP GET是用来获得一个资源的一个代表性。消费者用它(资源的代表性)从URI中重新得到一个代表性。服务提供者通过此接口不允许发生来自消费者任何的职责。
HTTP DELETE是用来删除一个资源的代表性的。
HTTP POST是用来更新或创建一个资源的代表性。
HTTP PUT是用来创建一个资源的代表性。
2.多数信息是XML格式的,并且有规范语言限制而写的。例如W3C的XML Schema或者RELAX NG。
3.简单的信息可以编码为URL编码。
4. 服务和服务提供者必须是资源,而消费者可能是资源。
除了标准的HTTP和XML处理技术,REST Web 服务需要很少的底层基础的支持,它现在被许多程序设计语言和平台很好的支持。REST Web 服务是简单且有效的,因为HTTP是最广泛可以得到的接口,并且它对多数的应用是很好的。在多数情况下,HTTP的简单很容易的胜过引入一个额外的传输层的复杂性。(译:林艳芹)