【IT168 评论】 面向服务的架构(SOA)是一种组织信息处理的方法。各系统为协同工作在各方面达成了协议,SOA通过减少这些协议的数量,能够降低信息系统互操作性的成本。如果SOA能得到大范围的应用,系统将呈现与现在截然不同的前景,这就好比当今货运行业有别于集装箱出现前的货运业时代一般。然而,目前的应用方式却导致了额外的开支却并未体现出这些互操作性的优势。将适用于数据库时代的范式应用于SOA中,会招致反效果,往往是愚蠢的,有时甚至是十分危险的设计。这些模式必须由新的思想和行为方式所替代,以确保SOA朝着接口更简单、IT方案更优化以及项目更可控的方向发展。这一点可以通过遵守以下十大戒条来实现。
引言:SOA的潜在影响
面向服务的架构(SOA)是一种组织信息处理的方法。这种方法以服务的形式描述所有交互活动,服务请求者请求代理完成某些处理,代理确保处理得以完成并将处理结果反馈给服务请求者。这种思维方式可以应用于业务级别,以描述各组织机构之间的交互;应用于功能级别,以描述组成业务流程的活动的交互方式;应用到信息系统级别,以描述系统及系统各部分的交互方式。每个级别的准则都是相同的:代理完成所需工作的方式与请求者无关,乃至与是否完全自动、完全人工亦或两者兼具都无关系。哪怕代理将部分或者甚至全部工作外包给其他代理完成也与请求者无关。所有请求者所需关注的是与代理就以下方面达成一致:请求及响应应该如何制定,以及服务的效果如何。
SOA被大肆宣扬为一种具有巨大潜力的范式,能够降低系统发展、测试及维护的成本。特别需要指出的是,SOA承诺可以通过大幅度减少达成协议的因素的数量,从而降低信息系统各模块协同工作的成本。采用SOA,诸如像计算平台和数据格式之间的差别造成的系统间通信屏障会较采用早期的范式要少得多。这使得更大范围上的协作变得可能,因为它减少了障碍,使系统设计师们不必被强行要求相互达成一致,就此而言,也使得系统配置员之间不必被强行要求达成一致。如果这种承诺可以实现,其结果将会是革命性的。就像汽车改变了城市区域形态,集装箱运输革新了货运行业,以及交易费用的降低发展了现代自由市场经济,SOA将开启新的合作模式。当SOA主导我们应用IT的方式,系统前景将与今日迥然不同,好比围绕汽车来设计规划的城市和围绕火车来设计规划的城市截然不同一般。对我们之中那些思维受限于目前技术的人来说,SOA可以产生多大的不同是难以想象的。然而SOA所提供的灵活性优势就好比汽车胜过火车一样:即便火车可以被制造跑得和汽车一样快,火车还是绝不可能像汽车那样提供门到门的运输服务。把火车站安置在每个车道的尽头,亦或甚至把铁轨铺设在每条道路上都是根本不现实的。
为何此影响尚未实现
为获取新范式带来的好处,我们必须好好利用其所能提供的各种新的可能性。遗憾的是,目前围绕SOA的言过其实的宣传对这些可能性的提及是言之甚少。大部分讨论似乎都关注于如何利用SOA帮助单独信息系统更快速地开发。然而,这并非SOA所能创造的最大价值之处。事实上,SOA是否真正能够改进以往的方法,即各个功能点通过某一共同的数据池(通常是以数据库的方式实现)来实现交互,还存在争议。使用SOA来构建单独、孤立的信息系统就像使用集装箱在加工厂附近搬运货物一样:当然,它限定了内部物流的顺序和组织,但是集装箱更多的是挡了道路而非提供帮助。SOA使信息系统间达到更好的互操作性,就像集装箱促使了运输商之间的互操作性一样。那是一种重要优势,因为从需求确定到信息系统可操作之间的时间周期通常很大程度上是由互操作性决定的。要使某一信息系统能够与其操作环境中的其他系统一起工作,那将会花费比重新构建这样一个系统更多的时间和精力。
关注于SOA在信息系统内部而非各系统之间的使用是情况更加恶化的征兆:因为看起来SOA是一种全新的处理我们一直以来所做的事情的方式,我们无法直接获取它所带来的收益。SOA概念和技术正为目前的系统开发范式所利用。这些范式还是数据库时代的开发产物,同时也带有数据库技术的一些限制。在这些限制下应用SOA将会导致额外的开支,而不能获得额外的收益。然而,这些“数据库化”的范式是如此普遍和有害以至于我们常常忽略了它们对我们的思维影响有多大。它们是如此根深蒂固,以至于我们会不自觉将其视作常理。遗憾的是,这样通常招致相反效果,常常是愚蠢的,有时甚至是相当危险的。它们导致了一种不好的方案,这种方案集合了数据库时代的缺点以及SOA不好的一面,而又不能体现SOA必定提供的优点。
需要改变什么
SOA范式有其自身的常识守则,较之数据库范式的守则截然不同。基本戒律有十项。前五项关于如何简化事物,使其比数据库化的范式要求更加简化——从坚持要点意义上更加简化。如果我们以此种方式简化事物,同一问题的不同解决方案相互间协作的可能性将大大提升。接下来的四项关于使IT解决方案优于同等数据库解决方案,这是通过阻止那些戴着有色眼镜、惯于数据库思维方式的人开发出无效解决方案来实现的。最后一项关于如何使IT更可控,尤其是组织系统开发以降低项目复杂度和风险。SOA使这些成为了可能——同样也是必须的——因为它让更多的功能交付成为基础架构。
简化之理论
在高空杂技表演中,高效的合作的基础是每个空中飞人演员完全默契地配合,对方会及时地在每个时点出现。一些空中飞人演员非常自信,他们经常蒙着眼进行表演。他们能够接到彼此正因为他们确定在某个特定时刻对方只可能出现在一个可能位置。
成功应用SOA以达到最大化的协作性与高空杂技表演非常相似。互操作性要求关于如何进行交流的解决方案从数以百万计减少到只有一个,交互双方都可以依赖该方案。这并不意味着其他方案有问题:这好比我们既可以靠左行驶也可以靠右行驶,但重要的是我们必须都靠同一边行驶。
当只有一方执行服务,一方接受服务时,只要双方协议好,具体使用哪种方案其实并没有太大区别。双方中任一方的特异性可以决定最终方案,无需做更多的沟通努力。毕竟,无论使用哪种方案,这些特异性总要被处理。但是如果是多方请求服务或者多方执行服务,那将呈现不一样的情景。此时使通信方案精简非常重要,如此,各方必须处理各自的特异性,无需面对另一方。
将信息通信与外科移植手术对比很能说明问题。成功的移植手术,要将一个人身上的器官移植到另一个人身上,要求该移植器官必须在多方面与接收者匹配,而其中大部分匹配因素与该器官的生物功能无关。换句话说,被移植的器官必须和接受者本身有相同的特征。因此,我们的器官不能像拼搭乐高积木一样随便被移植。目前的信息通信恰恰如此。当一个信息系统为另一个系统提供服务时,它们必须在很多方面达成一致。它们必须使用相同的词汇(元数据)、相同的由一方调用而另一方执行的功能集、对于每个功能请求应答数据内容的相同期望、相同的编码系统、相同的技术通讯协议、相同的用于信息传递的寻址模式、兼容的可预期的响应速率、兼容的确保消息不被丢失的技术、兼容的认证机制以确保双方安全通信而不是与冒名者通信、兼容的加密技术以及密钥管理以确保消息不被窃听或者篡改等等。为了促进互操作性,必须确保参与各方从彼此独立制定各自标准变为形成兼容的标准规范。只有当一些非常严谨的规则得到遵守时这才有实现的可能,接口才能减至精要。如此一来特异性将无容身之地。
严谨的规则都关注于如何使得服务接口更为简单。我们规定的越少,争议的余地就越小。
1.不了解你不需要了解的
你不需要去了解的东西不会伤害到你
SOA范式的本质在于使得合作各方或系统之间达成最少限度的协议却可以实现最大程度的合作。这是一种巨大的优势,因为任何你不需要了解的东西既不需要被测试也不需要被维护。你不需要去了解的东西不会伤害到你。假设40%的系统开发成本用于测试上,而高达80%的信息系统生命周期的成本被花费到了系统维护阶段,任何SOA范式让你无需了解的东西都代表了你能节省的金钱。
元数据
你最不需要了解的就是结构、含义以及容许值——这些元数据——不会被系统中筛选、排序或执行计算的逻辑使用的数据。你并不需要去了解这些,因为SOA技术使得数据和元数据同时出现。你的系统可以实时解读元数据,所以如果你要做的仅仅是获取、呈现或传送相应的数据,你完全不需要为系统构建元数据知识。在有相当精密的表示(presentation)功能的帮助下,它甚至可以为用户实现各种各样特定的筛选及计算,且只使用与已有数据同时提供的元数据,而不是内部构建元数据。
通过解读数据相应的元数据,而不是把元数据构建到系统中,你的系统不需要随元数据的改变而改变。需要改变的仅仅是源系统。想想如果遵守该守则,你能在开发、测试和维护上节省多少金钱!记住,在两个系统上做更改,平均来说,其复杂度是在单个系统做更改的四倍,因为其中包含了所有各方的协作。
对于很多面对客户的系统来说,表示以及特定筛选功能基本是其主要的功能。这些系统只针对最基本的客户数据要求内部构建元数据。这并不包括当前或过去的订单、客户通讯录、照片、信函以及任何可用于展示的其他数据,所有这些数据都可以用一种不需要这些数据本质相关知识的方式进行表示,内建于系统中。
技术
许多你不需要了解的事情是与技术相关的。有了SOA,你不需要了解你正在接口的系统是否采用“软件即服务”(Software-as-aservice),不需要了解实施该系统的计算机安放在何处,是哪种类型的计算机或者运行于何种操作系统,防火墙是如何配置,使用的是哪种数据库管理系统,亦或可以使用哪种交易管理系统。其他你不需要了解的事情是与你所通信的系统内部相关的。尤其是,你不需要去了解任何用于内部数据存储的元数据,因为任何其他系统需要同XSD一致的转换都是其自身的问题,而不是你的。
即便如此,使用SOA进行通信的各方必须达成一致的技术相关的标准还有很多选择。特别是有很多与Web服务相关的那些标准,SOA从业者将其统称为WS-*标准(*指可以使用很多可能的标签替换)。在一定程度上,这些标准提出得很恰当,因为SOA社区并没有满足于不去了解它不需要了解的东西;本文这个白皮书给出了一些指导以期降低由这些标准引起的问题的影响。遵守这些指导,SOA需要的先期协议将比其他方法要少得多。
设计稳定的接口
如果想获取SOA提供的种种好处,不去了解你不需要了解的东西会成为你的习惯。请铭记这点!比如说,当设计一个订货服务时,请记住服务请求者只需要知道,当他需要货物的时候该货物是否会有货,而不需要去了解当前的库存量。如果你的程序调用某一安全服务以判断请求活动是否被授权,不要在系统内构建任何超过其所需服务工作的知识。例如,如果安全服务需要使用输入到程序的安全证书,唯一必须做的就是传递该证书!对你来说,它们只是被封装在输入消息中的单个数据项。该证书是否是格式完整的XML也不要去验证。如果,由于某些只有那些负责安全的小鬼知道的原因,他们选择了违背标准的SOA操作或对证书进行了加密,那么这是他们的问题,不是你的。如果他们改变了任何与证书相关的东西,你的程序不应该为此做任何改变或调整。任何你不需要了解的东西不会伤害到你。当然了,除非你硬要去了解它,在这种情况下如果你们不想在SOA上浪费时间的话,其他人可能最好离远点儿。
不去了解那些你不需要了解的东西可能比你想象的要难。如果你开发专门用于与你通信的信息系统的信息检索服务,你的思路已经不对了,因为你已经把其他系统的知识归并到系统中了。需求中的任何更改将会迫使双方系统都作出更改。通常来讲,比较好的方式是采用数量有限的检索服务暴露系统数据,当检索服务结合在一起使用时,它们涵盖了所有相关服务的信息检索需求。例如,某个产品数据库可能通过好几个服务分别暴露出去:一个简单的仅包含编码、描述、部门以及产品定价的服务、一个暴露出所有该产品财务方面信息的服务,以及一个暴露出所有该产品物流方面信息的服务。许多系统仅需简单服务即可得到满足,大部分只需要部分数据而非全部,或财务或物流的服务,而有一些两者都需要,但此外没有任何一个需要特别接口的系统。这种工作方式被称为麦当劳方式:客户从标准产品中搭配出自己需要的产品。支持这种方式并不困难,因为不管怎样你都需要这些服务去支持面向客户的程序。你甚至可以用这种方式来支持非常特别的信息需求,因为那些不需要的数据可以在消费前就过滤掉。如果不想在巨无霸汉堡中放小黄瓜,扔掉它就可以了!这种方式的基本思路是提供过多的信息要比提供过少的信息遇到的问题少,因为接收方系统可以很容易通过程序过滤掉不需要的信息,但是如果缺少信息那就麻烦了。
不去了解你不需要了解的东西也会使得为支持业务流程所需的信息交互大大简化。在SOA的范式中,当你请求另一个代理为你做一些事,那就是你所需要做的全部。你不需要为代理提供可能有助于完成任务的或者是其必需的额外信息。在点菜时,确保有用于这道菜的原料是厨师的职责。你说出想要的东西,然后就可以静候佳音了。反过来,代理会使用信息检索服务来向你咨询所有信息,但是检索什么、何时检索以及从何检索,这些问题都应该由他来决定,你无须去了解,更不用将该知识归并至你的系统中。这样,在他那一端的更改几乎不需要你这边作出更改。比如说,如果他决定停止维护对你数据的拷贝,你什么更改都不需要做。
当然,不去了解你不需要了解的事情确实会导致效率低下。原本只需要一次交换即可实现的操作现在将需要多个步骤。麦当劳方式常常会导致原本一个服务即可满足却提供了多个服务的情况,另一边却还在检索信息,而这些信息又常常是冗余而非十分必要。总会出现一些情形,可以通过好的商业意识来优化这些通信模式。也会有很多场合你会想要优化用户接口,那也只是因为当前的表示设备并不擅长提供给用户吸引人的界面。但是在你优化之前,请考虑你会失去什么样的灵活性。另外绝不要想去优化那些尚未稳定的功能需求。
2.不要了解你还不能了解的事情
为时过早的规范冻结
数据库范式中,一个真正的难题在于:它要求在你还未足够了解并有能力去确定数据的具体结构前,就去做这件事。因为它们忽视了一个生活中简单的事实:只有当用户看到他们不想看到的东西时,他们才知道其真正想要的是什么。
其工作原理是这样:一旦完成了数据结构的设计,任何后续修改都会引起杂乱的数据库转换,除此之外每个访问该数据库的系统也会改变。所有这些改变必须都协调好,当所有对数据库的操作都限制在单个系统时候,这种协调是很困难的,但如果有多个系统都在操作,那就更难了,尤其是:如果其中有些系统被不受你控制的参与方管理的时候。事实上,在系统开发阶段做这些更改就已经很成问题了。其后果是,数据库设计早在系统开发阶段就被冻结,然后数据分析师们再去竭力修正这些设计。
现在的问题是数据分析师们面临着不可能完成的工作。他们必须在用户理解这个设计(且不说赞赏这个设计实际应用如何)前就确定该设计。只有在过了很久之后——系统已经构建好之后——用户才能对该系统有所体会并对其是否满足自己的需求作出评估。如果此时发现数据结构上有任何大问题,要想修复就太晚了。
SOA原型法
你可能会问:“SOA是怎么个不同寻常呢?”说到底,难道SOA不像数据库范式那样一样需要结构化数据吗?这个问题的简单答案:不管请求数据时,被人工代理处理还是被自动化系统处理,SOA都是管用的,并且就算数据没有被最优结构化,人们还是可以解读它。比如说,用户可以判断信件是否正在被发送至另一个国家,无论信件的地址是用行一、行二、行三和行四来表示的,而信息系统需要至少“国家”来作为数据结构可识别的一部分。
仔细回答这个问题就包括了对SOA原型法的讨论,这种讨论包括以下几方面:
识别将被构建到系统中的元数据。把它放在主命名空间中,用传统方式根据其结构把数据存储到数据库管理系统(DBMS)。例如,用户信息,这个元数据可能由用户ID和用户名构成。因为这个元数据被构建到系统中,所以为了使用这些字段而把逻辑也构建到系统中是完全有可能的,比如通过用户ID检索记录并基于用户名排序和筛选记录。
对每一条数据库记录,把不包含在主命名空间的所有数据放到一个单独的XML字符串中,该字符串作为一个单独的字段添加到数据库记录中。对每个XML字符串,构建一个二级命名空间,开发XSD,同时添加一个单独数据项到主命名空间。对用户记录的初步实现来说,这个字符串可能包括地址行一、行二、行三和行四的元数据。用户记录本身的XSD将会包括三个字段的元数据:用户ID、用户名和以XML字符串包括的附加的用户相关数据。附加用户数据的XSD包括每条地址行的元数据。
使用基于XSD的逻辑来为数据库记录的各相关层次获取及展示所有数据,这可以通过给每个XML字符串(包含对主记录的字符串)增加一个标准验证服务来实现。如有可能,利用某种工具来产生使用XSD的接口而不要自己去编程。该工具必须使用二级XML字符串所包含的元数据来将其解包,并且必须同时使用主、次两级XSD的逻辑来获取新记录。其结果就是一个可运行的原型,用户可用以评估预期使用的系统。
要尽量适应和修改基于XSD的逻辑以及验证服务直到用户对系统满意为止。就拿用户记录来说,一个新的针对字符串的XSD可包括以下元数据:街道地址、邮编、县市、以及国家。使用旧XSD存储的数据仍会正确显示,所以无需立即将其转换。而使用新XSD将会获取新的记录。
一旦用户和你确信元数据已经稳定了,那么请考虑把数据迁移到传统的数据结构和主命名空间。
当然,SOA原型法并不总是必要的。当需求受限于如此多的不确定性时,请使用原型法,这样先做原型然后再将其稳定比较经济。但是请记住这个肯定要比数据库化原型法要简单的多。在数据库化的时代,原型法只是可有可无,但是在SOA的时代,它便是家常便饭。不要将设计细节固定,除非你确定它们是正确的;就是这么简单。
3.除了要求的不要多做
产品驱动的服务分解
SOA主要的优势就是它是一个能被转化成技术的业务概念,不像数据库世界里那样,技术概念总想试图跟上业务的步伐。在SOA中,每个服务必须明确地增加价值,不只是在抽象意义层面上,而更具体地要针对那些调用方而言。发生的一切之所以这样发生了,是因为服务请求者要求其如此。通过不实现任何服务请求者没有明确要求的东西,服务可以被限定在它们的核心功能上。如果SOA中所有的参与者都积极这样去做,那么将会使互操作性大大增加。
SOA中最高层次的服务是业务交易:某个客户下了一个货物或服务的订单——除非订单被供应商拒绝——否则这就开始了一个订单交付。在SOA范式中,任何从接受订单到订单交付之间所发生的都可以也应该以服务的形式实现。为实现订单交付而要求的每个中间产品或状态,供应商会要求某些人或某些组织机构——不一定是供应商内部的组织——来执行交付。然后这些中间服务自身又可以分解成多个服务,一直到增加价值的基本组织层面。
层次服务分解是SOA范式中非常重要的一部分,因为它使服务交付通过服务水平协议的方式管理。它可以确保每个服务都有专人负责,并且服务消费者们知道他们会得到什么。
通用的中间产品和通用的服务
服务分解都是关于产品的。只有当组成服务的那些子服务不能立即执行时流程才会出现。例如,如果决定是否接受客户订单的服务要求:先执行判断订单价值的子服务,再执行确定客户信用状态的子服务,那么实现该服务就包含了一个流程。每个这样的流程只与一个服务相关。如果你发现有个流程不仅限于单个这样的服务,那么你很有可能是忘了把客户的初始需求建模为服务了。
有可能出现这样的情况,相同的中间产品——当然还有相同的服务——可能会被不同的高级别产品需要。比如,那些要求明显区分交付过程的商品,在中间产品的环节,其中的差别一般来说几乎微乎其微,中间产品其实也是由客户来支付——为了从客户那里赚取利润,我们需要金额、日期以及让我们可以冠冕堂皇地向客户要求支付的条款,实际是什么则并不用去理会。在这种情况下,正常的基准是如果存在通用的中间产品,那么它应该由单个服务来实现,而这个服务能够被多个高级别的服务调用。
这种服务只有结果是重要的——不是开始——因为收集对交付服务有用的信息是服务本身的一部分,而不是请求服务源头的一部分。需要注意的是:是否需要单个服务是由业务决定的,和信息技术没有任何关系。如果不管是现在还是相关的未来,交付相同的中间产品都是切实有用的,那么就应该有单个服务。除非在现在或相关的未来有商业力量发挥作用使中间产品发生结构性分化,那我们最好不要为每组需求分别提供相应服务。然而事实偏偏相反。在SOA,事物是由相同走向不同,而在数据库化的方法中,事物则是由不同走向相同。
带有多种行为的通用服务
你可能会问,如果需要两种完全不同的行为而你只为其提供一种服务,这样做的意义何在呢?难道我们还在被同样困扰数据库世界的“一刀切”做法限制?比如,如果我们出售两种类型的产品,其中一种使用固定价格而另一种则根据某些复杂的公式计算出变动价格,为什么不用两种结算服务,为每种特定的产品各订制一种呢?
这些问题很好,但问错了地方。它们是好问题,那是因为任何不能充分应对发生在问题域内变化的设计方法注定会失败。但是它们问在了错误的地方,这是因为根据问题域中的变化来调整方案的灵活性应该构建到服务中,而不是围绕着服务来构建。就拿结算服务来说,每次调用一种方法时,它应该决定这两种算法应该使用哪一种。那样的话,如果引入第三种结算算法,那么只有结算服务需要去做调整。请注意这并不意味着结算服务必须被设计成某种“功能较多”机器;它同样可以很好地为每个算法分别调用相应的子服务。这种选择——介于多功能解决方案和包含不同组件的框架之间——是一种可以根据服务来决定的选择,因为它不需要被服务请求者知道。在SOA中,这种选择更常见,但目前的做法则常常导致产生框架解决方案,因为需要多功能方案的感觉在很大程度上是由于不能从那些需要执行的信息里识别出服务请求造成的。这种需要高素质专家来实现的带有如此多参数的以一应十的多功能方案的日子不会长久了。
坚持要点
流程驱动方法也可以使我们分清我们是代表服务请求者做事还是为自己做事。以服务请求者身份做的事应该作为服务的一部分来执行,而其余的就不应该了。通过这种区分,我们可以让服务尽可能简单,这样可以在不需要改变各式各样其他东西的情况下替换掉该服务。举例来说,我们会生产产品来满足外部服务请求,但是维护簿记系统是为了满足我们自己的需求,而不是请求者的。如果要开发一项服务将客户订单转变成制造活动及账目簿记,那么只要我们实现一个新的簿记系统,我们就要去修改一次这个服务。这听起来似乎还不是太糟糕,但试想一下所有事情都是为我们自己而做,那就太糟糕了。包含最新数据的数据仓库的簿记、日志、储存、员工绩效数据的维护:所有这些及其他事情一般都由系统完成,这些系统随组织机构和时间的不同而不同,因此在业务服务中包含这些知识会降低互操作性,增加了用其他系统来实现服务替换的难度。我们可以通过产生通知的方式来避免此类问题,即:如果对这些功能很重要的事情发生了,就发出通知,然后它们可以使用通用服务检索处理事件所需的信息。
另一类不应作为服务一部分执行的业务活动包括那些一旦服务请求被撤销就无法逆转的活动。通常来说,这类活动包括诸如因客户订货导致库存量低于补货水平从而需要订购补给、注册新用户以及更新现有用户信息。这些活动是整个流程中的各个步骤,应使用单独的服务一一执行。
当然,这种思维方式可以与数据库范式紧密结合。但并不是其所特有的,因为它与SOA有关。结果是,许多SOA的实现与数据库化的思维方式背道而驰,而正是这种思维方式激发了他们以自下而上的方式识别服务,而非SOA的自上而下方式。在自下而上方式中,原本一开始为某个问题开发的服务也可以为其他问题复用,这多亏了设计它的人对于如何更广泛地应用做了认真的思考。SOA中,在多个上下文中使用某个服务是缜密设计的结果,而不是靠直觉,并且从设计之初就将所有那些上下文都考虑了进来。说到复用某一服务来交付某一通用的中间产品就好比说重复使用前门进入房子,不管那扇门是通向客厅、厨房,还是卫生间。你能想象厨房设计师说:“真妙!那家伙设计的室外通向客厅的入口正好可以被我用来作为通向厨房的室外入口!”吗?任何谈论“复用”(如复用支付服务)的人都还没有实现它。请注意,这并不是错误的,只是有点奇怪和没有什么启发性罢了。
服务遵从业务
采用SOA方式思考问题的一个结果就是SOA会使得服务依据其业务意义而非机械的实现来表述。例如,名为增加用户记录的服务是数据库化的,而名为注册新用户的服务就是SOA的,即便这两个服务做的事情完全一样。我们对服务的命名十分重要,因为它告诉我们是谁在请求该服务,以及为什么他要请求这项服务。在这个特定的例子中,SOA自上而下的方法会得到一个结论,那就是业务流程需要一个有效的用户注册服务,该服务通过修改现存的注册服务(如果有的话)来完成,而不是重新自动创建一个新的。在SOA中,这是用户注册服务的责任,而数据库化的方法却会把这个责任推到服务请求者身上。类似地,SOA注册用户服务自身会决定用户ID是什么,而数据库化的服务可能就会干脆让服务请求者做这个决定。
汇聚到单个方案
总的看来,SOA由上至下的思维方式使得很多设计决策只存在一个选项,而数据库化的思考者会把该选项仅仅看作众多可选方案之一。这是SOA很重要的一个优势,考虑到SOA是以互操作性为导向的,而互操作性要求我们行车时都在同一边行驶而不用去和我们碰到的每辆车去交涉。那些忽视这点的人--比如通过主张Web服务只是众多实现跨系统边界SOA的一种方式--能够一直成功的机会和那些只考虑下一步的棋手差不多。诚然,总是有比Web服务更简单的方法去连接两个系统,但是为了让呼叫中心或输出管理设施能使用相同数据你会怎么做?为了确保数据仓库能够在你把事件从一个系统转换到另一个系统时得到通知,或者事件一发生便能及时通知你的客户,你又会怎么做呢?在SOA的世界里,数据和事件必须在多个系统中可用,而Web服务是能够确保在低投资和低维护成本的前提下达到这一效果的最有效的方法。
存在这一明显差异的一个领域就是电子数据交换(EDI)。传统的电子数据交换(EDI)技术旨在确定组织之间通信可能需要的信息,并为该信息定义词汇。那和定义某一特定的信息交互不是一回事。比如,你可以使用相同的EDI报文来下订单、查询其进展以及修改它。两个组织想通过这些规范进行通信必须坐下来一起就这一词汇的使用方式达成一致。SOA分离了这些关注点:词汇由命名空间来处理,而这些命名空间可能会被多个服务使用,每个服务有各自特定的目的。
“SOA由上至下方式导致更具体的结论”的另一领域是这样一个问题:是什么筑起了一个编排过的流程边界。通常,这个问题会引起无休止的争论。比如,采用输出管理服务给客户发送确认信息是否应被编排为用户流程的一部分,如果是的话,它应该采用即发即弃(fire-and-forget)的方式处理还是应该由输出管理服务来报告动作成功完成?按SOA的话讲,所有这些东西都是用户意图的一部分,因此都应该被编排的。其他一些行为,比如考虑到新用户订单的更新数据仓库或者更新总分类,很显然都不是用户意图的一部分,不应该包含在流程编排中,哪怕它们是同一方执行的。
4.不要自己做琐事
通用功能
业务服务应该只包含特定于该服务的那些功能逻辑。它应该把其他功能都委托出去。那样的话,服务自身就可以尽可能简单。这使得设计、测试以及替换服务,如有必要的话,更容易。这是个基本的数学知识:新软件模块需要匹配的因素越多,那么同价位下的成品软件(COTS)的共性越少,而且若恰好有个方案可用时它也会更贵。如果可以将这些非特定功能委托给标准服务,那么就可以降低需要匹配的因素个数。
服务可以代劳的首要任务是琐事:都是些“家务事”而非真正业务相关的功能。这些琐事天生就是普遍的,换句话说完成这些琐事的方式并不是为支持业务上下文的服务量身定制的。
通用用户接口
当你得知信息系统最不应该做的一大琐事就是管理用户体验时你可能会觉得惊讶。这是一个通用的功能,应该尽可能的采用标准工具来处理。用户体验包括用户可以选择要执行工作项的工作列表,工作项执行的工具——比如通过启动一个用户界面(如果有的话)来关闭已完成的工作项。它包含了用户有可能执行的交易甄选,输入信息屏幕的表示——一般是从XSD生成——以及使用和交易相对应的标准验证服务进行验证。它包括了保持当前用户上下文环境,这样他就无需再次输入当前的客户、产品、项目、流程实例或者其他任何东西,而是可以使用这些默认值或者在必要时候重写它们。它包括了和当前用户上下文环境相关的所有文档的介绍。它包含了用户可能需要作出响应的提示对话框。
所有这些东西都可以使用无需包含任何业务知识的工具实现。总的来说,给用户提供一个统一、包含所有东西的环境远比为某个特定行为而优化的用户界面要好。如果有业务案例违背了这一原则,请至少记住这点:在稳定用户界之前,不要去优化它。
典型通用功能
其他的琐事还包括,但并不仅限于以下几个方面:
安全:建立服务请求者身份和访问权限。
通知:确认某一业务事件应通知哪些人。这包括了维护基于此的事件订阅。
输出管理:在线下进行信息通信,而不是作为一种服务响应。典型例子就是当客户请求必须被正式确认时,比如使用电子邮件来确认你刚刚通过浏览器所做的网上采购。对那些主动提供的消息也是需要的,比如每月的账单。输出管理必须决定通过哪条渠道去发送信息,以及使用哪个地址来发送。它应该把消息转换成接收方能够接收的格式,发送消息,并把消息添加到归档文档。输出管理包括维护那些被用来将数据转换成用户可理解消息的模板,以及潜在接收者的地址和渠道偏好。
数据转换:把数据从一种格式转换为另一个,把独立的各个服务打包为一个服务——用麦当劳的说法,开心乐园餐——以及分解拆包,将服务请求拆分成适用于不同人群的各个独立请求,汇集各个回应,排队及出列,或协议转换。
流程编排:编排某一流程,以确保按适当顺序且仅相关时来执行那些组成流程的服务,确保快要逾期时发送告警信息,以及确保因辅助信息或者逾期打断从而引起的新流程分支被启用。
归档管理:维护及访问相关的归档信息。这些可能是虚拟的档案,从某种意义上是展现给用户的信息,当他需要某个档案时可以使用查询来检索。对那些从数据库中抽取的内容,这被认为是正常的,但是没有特殊理由不对文档使用相同的方法。在某些情况下应使用设备来特别增加指派文档至档案中。
记录管理:维护那些不允许被更改的信息。
至下而上叙述
这些实现琐事的服务不能形成业务服务层次的部分。不能使用自上而下的方式去设计它们,因为这些服务都没有所谓的“上”。对这样的服务,使用旨在实现最大程度重用的自下而上的方法会更适合。这使得从这个阶段起就能够实现服务的优胜劣汰。
采用数据库化的方法,很少能够实际把次等通用功能用更好的替换,因为这要求修改所有使用该方法的应用。使用SOA则不同,这种替换很简单,前提是已经应用了“不去了解你不需要了解的事情”这条规则,包括其推论:服务请求不应该包含超过指定该请求必要信息之外的其他信息,而且服务本身应该在需要时主动要求更多信息。如授权服务,该服务由某应用调用,旨在决定是否允许某特定用户在某客户数据上执行某项功能——比如说:“我们的雇员Donald Jones是否被授权可以访问Acme Widgets company公司相关的财务数据?”。服务的简单版本可能具备处理某些特定情况的能力,在此特定情形下可以通过使用雇员功能对应表来回答这些问题。稍微复杂一点的版本可能会识别出Donald Jones属于某个或多个组的成员,除了个人权限外还拥有该组的权限。再更近一步,授权服务可能会使用用户证书去区别雇员和客户,并允许客户只能够访问他们自己的数据。一个完善的版本可能会使用标准化的服务去调用业务流程管理系统或者项目管理系统,询问Donald Jones是否已经被赋予了任何我们和Acme Widgets交易相关的职责。更好的做法是,授权服务会记录请求和应答的日志,而简单的版本不会这样做。组织可以从一个服务的版本切换到另一个而无需对调用服务的应用做任何改变。
也有可能设计出根据操作必需的条件自动配置自己的通用服务。例如,授权服务可以检查是否有服务可以告知它员工对某些特定客户有职责,并在该服务不可用的情况下决定只使用个人还是群组的访问权限。用这种方式,服务可以在很多组织之间复用。
5.不要在测试上自寻烦恼
为什么SOA更容易测试
对SOA缺点的一种看法是测试困难。这种看法完全不恰当,原因有很多。
首先,在SOA中使用元数据可以避免错误被植入到系统中。可以在元数据层次就对系统进行验证,例如,保证所有需要处理的数据在使用前就被汇总并校验。在整个业务流程范围内都可以实现这点。当你可以验证设计的时候就不要测试整个系统。
其次,几乎所有测试,包括所有系统集成测试,一旦测试基准被建立后都可以自动完成。但是,需要一些前提条件。表现层和业务执行层必须被严格的区分。好在这是使用SOA的一种很自然的方式。对所有输入,都应该存在相应的XSD。使用该XSD,可以生成测试记录。同理,也可以生成带有预期输出结果的测试记录。在测试过程中,不能产生可以证明系统运行正常的任何输出地方,必须在测试脚本中添加专门为此生成的附加输出的查询语句。当测试开始运行时,测试记录被一条条输入系统,然后输出的结果自动和期望的结果进行对比。这会产生一个异常列表,其中每项都应仔细考虑。测试可以按需进行。自然,测试的结果可能取决于存积在数据库中的数据,所以这点需要进行弥补。而且,系统不可表现出时间相关的行为。系统必须有能力响应每隔一段时间(它对自动化测试序列更适合)就产生的事件,而不是花上一周时间去等待某个基于时间的触发器被触发。用户界面的测试应该单独进行,而且永远不在集成测试中使用。
第三,SOA的设计趋向于产生更加健壮的系统:系统出错的机会更少。SOA减少了信息系统为了协同工作而需要达成协议的因素数量,这样一来,导致在某关键因素上产生分歧的设计错误的概率也减少了。就算真的出错,也能够在造成损害之前检测到。使用SOA,消息在被处理前会被验证,这样可以判断消息是否格式正确、是否符合相应的XSD。
可行性测试
最后,作为数据库时代特有的产物——测试环境和生产环境必须严格区分,从此不再需要了,而且有时候这也是不适合的。这是很有可能的,这是因为我们不再实际进行系统测试了,而是对测试通路和信息处理的方式进行测试。SOA提供了三重安全的、有效区分测试消息和生产消息的方法。除了被封装好的消息,其他每个消息自身和相应的命名空间都包含版本号。而且每个消息都包含一个标签用以指示它是用于测试还是生产。所需的只是一个SOA网关,它存在于防火墙内部,对每条进入消息进行如下处理:
校验消息以确定其是否与一个已知XSD的版本相符(被封装好的消息除外)。
使用我们对相应XSD的副本对消息进行校验,以确定其是否有效。
如果消息用于生产的,就验证消息版本号是否被允许用于生产。只有这样,消息才能够被传递到生产系统。其他所谓的“生产”消息都会被拒绝。
如果消息用于测试,消息可能会被传递到指定的测试版系统。在特殊情况下,消息如果只是用来做数据检索,那也有可能被传递到生产系统。
只有在消息被完全测试过后,生产版本的注册库和XSD才能得以更新。
这样的处理方法不仅仅只是三重安全的,而且使得消息的路由能以一种合乎实际的方式得到测试。这也大大降低了从测试系统切换到生产系统时重新进行配置的需求。因为这种重新配置天生就是不可测试的,常常成为错误的根源。发布经理只能通过在半夜或者周末发布新的版本软件来弥补这类错误;这样,就算新版本出现了任何错误,也可以在有人发现错误之前恢复到老版本。但如果这样的变化影响到了其他组织那就没有办法这样操作了。SOA发布管理要简单得多!
我们对于SOA测试的一般认识是时候该改变了。SOA是能够把测试需求和设置测试的工作减少到最低的一种方案。它能使重要测试更自动化的完成,结果也更好。
完善之理论
SOA使得信息系统的开发和部署能够比使用数据库化的方法支持更为丰富的用户体验。这样的系统能够涵盖更多的信息格式、更广的行为集合,其行为上也可以达到更高层次的统一和一致以及更加可靠,不管是从客户还是从组织内关注合规的人员的观点来衡量。然而,要想获得这些好处需要我们跟已有的数据库方法实践说再见。
6.始终信守你的诺言
为什么数据库不能一直信守诺言
接收一个服务请求的动作是通过定义一个承诺,即向请求者承诺服务请求会被执行,来确定的。这种执行定义了一个流程,其至少包含一个步骤,但通常是多个步骤。
数据库化的思考和流程不能融洽相处。从它们各自的本质来看,数据库就像是一个个孤岛。而孤岛会促使偏狭地思考问题:任何孤岛之外的东西都不重要。可以通过数据库中的事务概念来形象地解释这个问题:某个工作单元把数据库从一种一致性状态转移到另一个。在一些特殊的情况下,该概念可能会被扩展到多个数据库,虽然可以通过两阶段提交技术来做,但这也有局限性。逻辑一致性可能需要贯穿整个业务流程得以维护,而不只是恰好在某个时刻;需要在信息改变波及的所有地方去维护,其中不仅包括数据库还有流程管理系统、信息以及发送和接受信息的人工代理,而这一切从数据库世界的观点看来是完全陌生的。
SOA交易概念
对数据库世界陌生的东西对与SOA来说却是再自然不过了。业务交易——实现它的一般是一个流程——就是服务。为了理解SOA何以能很好支持逻辑一致性需求,理解业务交易的需要很重要。业务交易由下面元素组成:
厂商给客户提供信息,客户据此可作出采购决定。一般来说,这种信息包括出售商品和服务的属性、得到该商品的条件——包括,当然,价格——以及可用性。从法律的角度,厂商所描述的这一信息是真实的。
用户基于厂商描述的信息下采购订单。
厂商核实该采购决定依据的信息是否仍然适用,如果是,则确认该订单。如果有变化——可能由于产品或服务已终止,或产品已经涨价,也可能是货物或服务的规格已经变更——那么需要一些处理来决定到底应该如何做:是不管三七二十一继续提交订单,还是通过协商修改订单,或者干脆取消订单。
厂商和客户双方履行采购协议中各项条约。
SOA怎样维持一致性
SOA通过多种方法维护业务交易的逻辑一致性。第一,所有暗含对前一个状况改变的通信都要使用能够保证消息安全交付的协议来完成。只要厂商或用户做出某个承诺,为实现该承诺所要做的动作就应该包含这样的改变。这样的话,客户和厂商就不可能对当前业务状态持有不同的看法了。
第二,数据库的逻辑一致性和流程管理系统中处理过程的记录可以通过两阶段提交协议来维护。跨多个数据库的逻辑一致性通过一连串这样的两阶段提交维护。首先让数据库A和流程管理系统同步,然后流程管理系统再和数据库B同步,以此类推。
第三,从厂商给客户展示产品到订单下达期间,厂商面对的任何改变都可以使用乐观锁并发控制机制来处理。这种处理方式对SOA来说很自然:判断是否存在相应改动的过程可以完全自动化。因为SOA使得数据在被用来作决定的同时也可以进行访问,找不到乐观锁而需要人工介入的情况几乎鲜有发生。
最后,一笔交易的中止——比如说用户撤销了订单,原因可能是用户没有能力支付,或者用户去世了——使用SOA可以相对容易地处理。因为在交易上下文中使用或产生的记录可以被清晰地识别,所以可以确定需要哪些补偿信息用以纠正用户和厂商的不同认知。因为哪个数据库更新和该交易有直接关系是很清楚的,在数据库中的哪些变更需要使用补偿交易服务做回滚也很清楚。假设,交易中止的发生相对不那么频繁,使这些活动完全自动化通常是高投入低产出的,但是你的设计必须要考虑到这些。
请注意业务交易的范围限制在那些为了处理某个服务请求而直接完成的操作。在SOA中,编排你自己的流程并提供事件通知给他人,是一条守则。如果服务中止了,那么有必要发通知用户这一个变化。至于他们要怎么处理,则完全是他们自己的事。
也请注意,创建用户服务请求的内容,严格说起来,应该在流程处理之前进行,而不应该作为流程处理的一部分。这真的不是你该做的事:原则上,提供消息的XSD和消息验证服务给用户就够了,让他决定是从键盘录入数据还是从他自己的信息系统以某种方式直接生成数据。对消费者来说,这并不是——尚未成为——一个可行的方法,但采集数据和处理数据是两件独立的事情,并使用不同工具在各自的环境中执行这些事情,对于这一点仍然是有效的。同样是数据采集,有很多实现方式,这取决于用户的期望以及他们和你沟通的渠道,但不管怎样都应该只有一个服务去处理这事儿。
7.不要将自己禁锢于模型
数据库只是模型,SOA代表更多
领域模型是领域本身的体现,操作领域模型要比直接操作领域更简单。绝大多数的数据库都是模型。它们以这样一种方式代表一些管理的、物理的或者社会的领域:相关领域的问题都可以通过查询数据库来得到答案,而存在于领域中所需的行为可以从数据库内部得到指示。比如说,通过访问数据库查询用户的地址信息要比跟随用户到他家然后抄下他所进房子的门牌号要方便的多。而且,在数据库中对记录进行计数也要比清点一个城市有多少人或仓库里有多少产品要容易。原则上,提供对这些功能的支持足以确定数据库的数据结构。尽管这样,因为一般不太可能事先就能明确所有这些功能,所以我们使用数据建模技术对领域中感兴趣的对象进行分析,包括对象之间的关系,以及信息项(它们会告诉我们关于其自身的一些我们可能想知道的东西)。例如,若数据库和用户有关,那么每个用户通常都应该存在对应的数据库记录,包括一些数据库使用者感兴趣的与用户相关的信息。因为数据模型更多是基于功能上的考虑而不是某些特定数据库的使用,所以将数据结构建立在这种模型之上会使数据库能够更易适应各种未预见的需求。数据库在语义上被结构化了;换句话来讲,数据库是根据其表达出的意思来构造的。
对没有实现数据模型的数据结构,数据库技术就没那么方便了。它实在不能在描述、文本、图像等方面做很多贡献。相反,SOA却能够很好地处理文档、记录,就像可以很好处理那些根据数据模型构建的数据一样。SOA允许单个设计能够处理语义结构化信息和文档。尽管如此,由于数据库系统支配了我们的思维模式,所以当应用SOA时免不了很自然的会坚持其局限性。但是在SOA的世界里不存在特殊的理由要去应用这种限制,任何理由都不能够这样做。
超越模型的益处
将语义上结构化的数据和一些像超链接、文本、图片以及音频片段的东西结合起来的一个主要原因是创建更为丰富的用户体验。对消费者来说,这是必须的,而不是可选的。对你雇佣的知识型工作人员而言,这会使他们做事更有效率。只有对从事日常管理的员工来说,它才会成为一种障碍。然而你应用SOA越多,你对这些人员的需要就越少。他们从表单键入数据的工作可以外包给任何人做:你需要做的仅仅是扫描每个表单然后把图像发送给代理,代理本质上使用和用户一样的Web表单去键入数据。至少真正需要雇员日常处理的工作都可以用自动化完成。
不要让自己禁锢于数据库数据的第二大原因是,把数据库化和基于文本的数据结合起来是目前维持营运合规所需记录信息和审计线索最简单的方法。数据库因其特有的性质并不适合这样的最终目的。因为通常某个数据库是为担当某种管理现状模型而构建的,所以当该管理现状改变的时候,它应该很容易去做相应改变。数据库管理系统就是为了方便这种改变而设计的。当它们被用来维护不允许被更改的记录时——比如,簿记条目——设计者不得不把各种安全防御构建到系统中,从而防止对记录的恶意操作。即便如此,神智清醒的外行人也不会去信任数据库的。为营运合规目的需要的记录信息和审计线索必须被委托给记录管理程序,然后通过SOA来与数据库系统进行关联。
使用SOA,把语义结构化的数据和其他形式的信息表示连接起来很容易。这使得它是内容管理和内容表示的理想之选。数据库可以将超链接保存到其他信息中。比如,我们可以用交易的数据库记录来存储产生该交易的输入文档的超链接。当显示交易记录的同时,链接也跟着展现,而且可以让使用者通过单独的服务去激活它。开发一个使其能够从归档文件去访问文档的服务不会比开发一个从数据库访问数据的服务更困难。当然了,除非你的归档文件不具有SOA能力,此时第一件要做的事情就是替换掉它。
但是,反过来也一样。不仅语义格式化的数据通过链接来丰富记录,而且记录也可以通过链接来丰富语义格式化数据。当你将记录存储于归档文件中的时候,与记录相关的语义结构化数据通常会包含所有为其索引而需要的信息。几乎不可能不需要手工索引记录。可喜的是,每当交易在数据库中进行一次,索引就可以自动对其更新从而逐步丰富起来。
集成数据库化和基于文档的数据有另一大优点,就是很容易支持数据的多个版本。在数据库世界这是说不通的,因为数据库作为一种模型,且作为一种有用的模型,它必须在对管理现状模型的任何提问作出至少一个非常好的的猜测以应答。一个文档,实际是某个特定组织在特定时间以及特定环境所做的一个声明,而且这也很有可能——经常被用来了解——相冲突声明的存在。
文化冲击
请注意,数据库化的思考者不是唯一在统一文档和数据库世界遭遇困难的人。那些思维方式受当代文档和记录管理系统影响的人会遇到更大的困难。一时之间,归档文件成为业务流程的一部分,而不是流程完成后形成。而索引不是人工完成,也不是一个文档一个索引,而是自动并持续更新的。索引也不再是归档的一部分:归档仅仅只包含文件,而索引分开维护。因此不需要把自己局限于一个归档,或者只局限于你自己的归档。这些改变是如此深远,很难想象那些适应了旧世界的人也能对新世界适应。
8.不要使用快照模型
具体而正式的历史信息
我职业生涯中最大的错误就是设计了这样的数据库,其中所有服务请求都被给予一个时间戳,以便数据添加进去后,服务可以根据指定时刻数据库存放的数据内容来响应,而不是根据当前内容。这个数据库极其昂贵,把执行速度拖累得就像龟行,而且没能起到很大作用。当用户想看看过去某个特定的结果是怎么被计算出来的时候,他们不免只能够查询归档文件,因为这些归档文件总是会包含之前与用户沟通的结果。而这也正是他们想要知道的东西。
请注意数据库的用途不是去记录过去那些成为问题的情况。数据库是现实世界某些部分的模型,以及在过去某一段时间里现实世界那部分的状态——它的具体历史——可能和模型的目的非常相关。但是,如果它想要再现自己在过去某个点的状态,换句话说去记录它的正式历史信息,数据库就太把自己当回事儿了。
SOA如何支持正式历史记录
SOA方法提供了一种再现正式历史信息的高效方案,不只针对单个数据库,而是针对组织在其管理流程中使用或者产生的所有信息。SOA对组织信息更新所需的数据收集和实际执行更新的分离让数据可以在记录管理程序中得以归档。一旦应用了SOA,这就可以自动完成,而且合并新的数据集几乎不消做多余的努力。这样一来,你可以获得由自己雇员所做的所有输入消息以及更新。
对即将离开的线下信息情况来说,可能更简单。SOA厌恶将琐事与对客户的附加值混合起来,这种混合导致客户很自然地会去使用输出管理服务以确保离线信息通过适当的渠道发送至目标接收者,发送时要确保地址是接收者会使用的,并且格式是接收者确实能收到的。输出管理服务能够自动记录输出信息。
尽管如此,还是有个问题。组织使用SOA传播信息的难易程度有可能导致对外界的服务响应数量大大增加。通常这些服务响应都隐含了组织对他们声明内容的承诺。如果它们不正确的话,组织可能会陷入法律难题。SOA处理这种问题的标准方法包括以下指导方针:
实现和SOA交易概念相一致的业务交易。
将放弃承诺包含在对全部信息进行检索的服务的服务水平协议中。
在需要使用时才访问数据。这样可以使数据尽可能的最新。
不要撒谎。如果一直讲真话,你将很少遇到关于信息不正确的投诉。
如果使用放弃承诺还使得你不得不对声称信息是不正确的声明作出反应,那对每个服务请求和回应进行日志,采用标准的组织范围的服务。
这种工作方式要比数据库化的方案组织起来更简单,因为不需要对每种消息类型都要求一种额外逻辑,而是调用日志服务,在日志服务中整个输入或输出消息都被当成是单一的数据项来处理。
9.不要相信系统
SOA安全
如果你的身体使用与大多数Web网站相同的防御规则来抵制外物,只消一天你就会死亡。我们生活在一个怀有敌意的世界,这里唯一能够避免信息系统遭受攻击的办法就是让它们不可访问。在这样的世界,SOA是一种绝妙的安全概念。原则上说,唯一必须让其通过防火墙的消息是牢牢封装好的XML消息。它们可以以这样的方式通过防火墙:在进一步处理之前它们会接受格式良好、XSD一致性以及授权有效性方面的检查。这样,造成危害的可能性非常小。缓冲区溢出只能够在安全防御区内爆发,而SQL注入不过是我们对其充耳不闻的一种语言上的祸害。像这样畸形的消息在其作出任何伤害之前就能被识别出来。
认识到这点很重要:即这种方法的优势是基于消息的认证和校验而非系统的。这是必要的,因为封装好的XML常常通过那些对其内容不负任何责任的系统传递,以至于检查消息是否来自认证过的系统并不能保证什么。它更健壮,因为某信息系统或电脑一次成功侵入并不会为其他侵入打开大门。
SOA的安全和数据库时代基于系统的安全形成了鲜明对比。有了基于系统的安全保障,对每个消息类型和数据项来说,每个系统的任务就是避免缓冲区溢出。有上千个点可能成为出错点。因此,就少不了薄弱点存在的可能性。而另一方面,某个SOA关守(gatekeeper),可以在单一的点上完成所有这些。基于系统的访问安全倾向于把授权控制构建到系统中,这不仅使得跟踪记录变得几乎不可能,而且引入结构性改变(比如把外部组织的客户添加进来)也是很昂贵的花销。
使用SOA关守的另一大优势在于可以保证所有输出消息被适当加密和签名,这样就没人能够窃取消息或在传输中篡改消息。原则上,大部分WS-*标准都可以完全由SOA关守处理。
超越基于系统的授权
基于系统的安全也会产生了一些心态,这些心态更多的是由基于系统的思维决定的,而不是如我们所愿意承认的那样。因为系统是围绕着功能点和数据结构构建的,授权就是这样表达的。例如,雇员要么有权限改变产品价格,要么没有,这是基于他在组织中的角色而定。对后端雇员不会遇到这种问题,但对管理层雇员以及用户而言,这就不适合了。对他们来说,允许他们查看和完成事情的决定因素是横跨所有系统和数据库的手头客户的信息切片。一个简单的信息安全文献扫描就足以构建那些信息安全咨询公司尚未企及的一点:对每一个基于切片的访问安全引用有数以千记的基于角色的访问安全。从积极的角度看,涌现出大量的概念,它们对充分发挥SOA提供的各项技术(基于声明的访问控制、联邦身份及网络边界去除技术)的优点来实现访问安全有长期正面的影响。
可管理之理论
想要取得SOA最大化的利益,仅仅采用新的行为准则是不够的。组织机构考虑自身的方式及IT方式也需要改变。否则当前的组织将还是退回到老样子,并不是因为它想要这样,而是因为它把这看作是控制自身日常行为的唯一方法。为了克服这点,你必须从项目的组织去着手。
10.不到最后不要扔掉基础设施
为什么要担心基础设施?
SOA就是要使基础设施从业务中分离开来,不只是在功能上,而且还在项目管理上:项目经理应该能够把思想集中在他负责开发的服务的商业附加值上,而不是担心基础设施。业务项目经理应该去组织开发一个作为项目一部分的新授权服务,而不是去构建一个新电话局,这不会荒谬到哪里去。让项目经理承担类似这些事情会导致他要协调的事物数目增加,从而进一步导致其工作复杂性不成比例的增加。就算让他等待直到其他项目经理把基础设施交付了,这也是应该尽可能去避免的。
上述评论适用于硬件基础设施也同样适用于基础设施服务。计算能力和网络容量应该总要超过需求,这样的话实施新服务的项目经理就不用担心基础设施是否能够为比原先预想更多的每天上千个服务请求提供支持。鉴于软件开发一般都比IT基础设施要贵出一个数量级,我们最不想要的就是:系统开发项目由于那些需要确保IT基础设施可用性的官僚性流程而被纠缠停滞不前。
基础设施:SOA有何不同
好消息是用SOA的方式去提出你的要求然后静观其变会得到简单、稳定的基础设施服务接口。这也就是为什么在你没有启动任何业务项目前,没有必要去实施世界上非常先进的基础设施服务。这些服务的复杂性不在于用来调用它们的接口,而在于它们从其他来源——或者从自我维护中——要求的信息,以便生产一个优化的结果。因此,完全可行的办法是有了初步的基础设施服务就启动项目,然后在业务项目中花足够多的时间去使用这些服务来做测试和生产。
坏消息是SOA会导致更多的功能被分类为基础设施。尤其是,每个琐事引起一个通用的服务,而这一服务必须作为基础设施的一部分而不是成为需要它的每个业务功能的一部分来实现。虽然就本身来说不算很坏,但这的确导致了一个新问题:对于基础设施的每个部分来说,如何去组织安排各项事宜才能使既拥有权限又具有资源的人去确保它能按时可供使用而且具备了适当的功能和容量。组织若是不能妥善处理这一问题的话,就不能很好地实施SOA——事情就这么简单。
敢问路在何方?
虽然组成SOA的要素已存在多时,但SOA本身是全新的。就像集装箱一样,它不只是一种全新的处理我们一直以来所做事情的方法,因为它使得我们能以新的规模合作。而且SOA根本不是一项新技术,而是一种新的思维方式。SOA与我们现在考虑问题的方式是如此不同,所以要是你通读本文几遍才开始理解其中的意思,你并不用感到难为情。你对此的自然倾向是,你会觉得这些建议不切实际或没有必要或者两者皆是,而使你根本无法对它作出评估,在这之前你还需要适应一段时间。
公正地说,也会出现SOA方案对你不直接起作用的情况。比如,你可能会从一些厂商那边以打包的形式获得你所有的系统,而那些厂商对采用本文中提到的方式来应用SOA一点特别的兴趣都没有。那样的话,把本文中所给的建议作为指南:使用它们来判定是否你做的选择会把你带向正确的方向。
SOA是如此之新,所以并不是所有为了充分利用SOA而被我们需要的概念、工具及标准都已经可用了。我们不能期待现行的关守(gatekeeper)像一个SOA关守(SOA gatekeeper)一样为我们代劳一切,现行的用户接口设备对于封装的XML有困难。更糟的是,正如本文表明的那样,当前SOA世界里存在很多扑朔迷离、多余或者错误的东西。目前,SOA概念和技术的应用无论在哪里都没有达到SOA互操作性能力所能够达到的层次。我们遇到的互操作性问题往往都是由于其他一些人选择了实现稍有不同的众多WS-*标准中的子集。那些数以百万计的多方通信的可能方案已经减少到很少的一把了,但依然还是实在太多了。
不管怎样,我们开了个好头。接下来我们可以沿着这条路继续走。SOA也同样如此。我们不需要为了进步而要去了解我们还不能了解的东西。向前看,我们有极大的潜力去使得事情更简单、更可靠,更具可预测性以及功能更丰富。是时候出发了。