近几年来,我一直从事着和面向服务相关的底层软件研发工作,逐渐的形成了一些自己的看法,其中我觉得比较重要的看法就是服务需要一个更准确细致的定义。简单来说, 服务的本质就是行为(业务活动)的抽象。
为了更好的阐述新服务的概念,并方便与传统的SOA中定义的服务有所区别,我将新的服务命名为 S++(Service Plus Plus) ,接下来我会通过对比S++与SOA和微服务的区别、S++与面向对象的差异来说明这个新的概念。
为什么要重新定义服务呢?其中一个原因就是服务从不同的角度看其实是不一样的,我们举个例子。
服务到底是什么样子的?这个问题很有意思,有点儿横看成岭侧成峰的感觉。是的,传统的无论是SOA定义的服务还是微服务定义的服务,一个服务只会有一个最全面的定义,这样的定义太复杂了,最后只有技术人员能看得懂。那么如何让业务人员也能看得懂呢?一般来说就是文档在起作用,但是文档有个问题就是只能看没法改,任何对业务服务的修改最终必须还要通过技术人员。
所以,传统的服务定义是业务和技术混杂在一起的,能不能有一种方法让所有人看到的服务都是一个样子而且都能看懂都能修改呢?这就是S++要做的事情,S++通过服务的 业务与技术分离 彻底将传统服务中和业务无关的技术成分剥离出去,放到服务的外延中去,让服务内涵成为纯粹的业务描述。
另外一个原因是,从服务流程梳理人员的角度看,传统的服务抽象度是不够的。举个例子,一个业务流程需要完成先在帳户上扣款然后再缴费这样的业务。对于流程编排人员来说,缴费这个服务可不是一个服务,首先有很多种现存的缴费种类(电话费、水费、煤气费….),而且未来还有很多种可能的种类。
我们不可能在一开始就包含所有的业务可能,但是我们又必须在一开始就包含所有的业务可能,否则我就会陷入不停的修改之中。因此,为解决这个矛盾我们需要一个更加抽象的服务定义,在流程中只需要调用抽象的业务服务,这就是S++需要解决的另一个主要问题。
对于SOA,推进结构化信息标准组织(OASIS)和开放团体(Open Group)均给出了正式定义。OASIS将SOA定义为:
A paradigm for organizing and utilizing distributed capabilities that may be under the control of different ownership domains. It provides a uniform means to offer, discover, interact with and use capabilities to produce desired effects consistent with measurable preconditions and expectations.
Open Group将SOA定义为:
Service-Oriented Architecture (SOA) is an architectural style that supports service-orientation. Service-orientation is a way of thinking in terms of services and service-based development and the outcomes of services.
A service:
Is a logical representation of a repeatable business activity that
has a specified outcome (e.g., check customer credit, provide weather data, consolidate drilling reports)
Is self-contained May be composed of other services
Is a “black box” to consumers of the service
业界基本的认知是,SOA是一种架构模式,是一种面向服务的思维方式。对于服务的定义,Open Group认为服务是一种可重复的业务活动的逻辑上的描述,是一种自包含的、可组合的“黑盒子”。
微服务在服务定义上,与传统的SOA差别不大,在实现上强调应用的颗粒度足够小,当然小到什么程度也是争论的一个话题。在我看来,微服务“微”的并不是服务,其实微的是应用(后面我们会谈到,服务的颗粒度是和需求相关的,是不能随意变大变小的)。
S++认为, 服务是一种对行为(业务活动)的抽象 ,这种抽象不仅仅是简单的屏蔽掉业务活动内部的细节,同时需要对相同类型的活动进行归纳形成统一的行为模型。所以S++包含两个层面的抽象:
从实现上看,SOA允许各种不同的技术来表达SOA的架构理念包括WebServices、REST、DCOM、CORBA、JAVA RMI等等,其中业界比较流行的方法是WebServices方法。从理论上讲,架构的实现是与技术无关的,但是从实践上看并不是所有技术都能很好的实现某种架构的。
以WebServices为例,WebServices事实上属于传统的面向对象技术的一种衍生技术,即所谓面向接口的技术(类似的比如Java的Interface概念)。这会导致在实现过程中系统间依然是以对象为载体的交互模式,这就必然带来系统间的耦合。
从S++的定义看,由于引入了更高层次的抽象,完全采用传统的面向对象的技术来实现势必就行不通了。所以,必须有专用的S++容器承载S++服务以及处理S++的多态模型转换。当然,S++同时必然也兼容了传统的面向对象的技术,对于用传统技术构造的业务系统而言,S++化的过程是透明的无需做针对性的改造。
微服务更强调实现的轻量化,架构上采用点对点去中心化,在协议上尽量选择更轻量的协议,以便提高系统的性能,这与微服务架构的颗粒度有很大关系。在S++看来,任何协议都属于服务的外延部分,并不影响服务内涵的定义,就像我们从不同角色去看骑大象一样,对于不同的服务访问者和实现者来说,采用不同的协议和技术手段都是可能的。从这个角度看,SOA和微服务都是S++的一种实例或实现。
从架构上看,S++认为只要有需求,那么中心点是必然也必须存在的,性能问题不能成为借口。架构是为应用服务的,不同的应用适用不同的架构,比如服务组合必然会引入一个局部的中心节点,不能为了技术需要而牺牲应用的需求和架构的平衡性。这一点上,S++与传统的SOA和微服务都是有差异的,S++推荐的架构是介于SOA与微服务之间的多中心架构,根据业务需求划分不同的区域,在每一个区域中根据自己应用的特点选择不同的技术。
传统的SOA虽然在服务的定义上与面向对象有很大差异,但并没有自己专门的实现方法,所以真正去实现SOA架构的时候依然使用的是面向对象的方法。现存的SOA实现方法,大抵是基于远程对象来进行服务的封装和调用的。
我们知道,要访问远程对象的客户端必须在编译时刻引入远程对象的stub类,而且由于面向对象中多态的实现必须由调用者来决定,所以服务访问者必须包含所有可能的stub类才能够在运行时刻实现多态。一旦服务提供者增加了一种新的派生对象,服务消费者必须在编译时刻引入这个新类的stub才能访问,这就导致了服务提供者与服务消费者之间的紧耦合。举个例子:
一个消费者需要调用 Person.hello()服务,Person是个抽象的类,服务提供者实现了Man和Women两个具体类。对于服务消费者来说,多态的实现必须在消费者端进行确定,必须在程序中明确指明Person p = new Man();或者Person p = new Women();如果服务提供者增加了OldPerson这样一个新的对象时,服务消费者是无法访问的,因为此时的运行时刻不包含OldPerson的stub类。
反之,对于S++来说,服务的定义是不需要依附于对象的,上述例子中服务消费者只需要引入hello服务的抽象定义hello(Sting personID)。当这个抽象的服务访问发送到ESB(如果没有ESB就需要服务提供者具备多态容器的功能)上以后,ESB会根据预先约定好的服务定义和服务Cast规则进行运行时刻服务实例的选择。对于传统IT开发人员来说,这一过程更像业务的过程(通过一个业务字段的内容来判断调用哪个业务流程),其实对于SOA服务的开发人员来说,这个过程是透明的,因为服务定义人员在定义服务的时候已经约定了多态的规则,因此这一部分业务已经被技术化从而可以被技术平台直接实现。在SOA架构中,类似的业务功能技术化的必备功能还有一些,比如传统的冲正被用于全局事务一致性以后就必须技术化。
S++相对于微服务,在耦合性上也是有很大差异的。由于微服务将应用拆分到足够小,甚至可以小到一个对象一个应用,这样原本存在于对象间的业务逻辑必然就会造成微服务之间相互调用,从而形成应用间耦合性;S++认为对象间组合逻辑应该交由一个S++容器去完成,这样就将微应用之间的耦合消除掉了,但是同时也产生了一个业务逻辑调度中心。
面向对象关注的是对象的内在属性,只要内在属性一致,我们在建立对象模型的时候都将其抽象成一类对象,所以内在属性的是描述对象的不可更改要素。这种特性使得OOAD的方法非常适合用于建立系统内部数据模型,通过对系统内部实体的抽象和描述,我们可以获得系统完整的数据结构和模型,而系统的功能就通过对这些对象的增删改查和计算等动作来完成。
而面向服务则不然,面向服务并不关心服务的内在逻辑,反而更关心服务的外在表象,只要对外的表现是一致的,我们在建立服务模型的时候就将其抽象为一类服务。比如缴费类服务,无论是缴水费还是缴电费,其外在的表象都是一致的,从行为模式上我们就可以抽象一个缴费的服务。面向对象中对象内在的属性是不可更改的要素,那么面向服务中构成行为的输入输出内容则成为不可更改的要素,比如打球这种行为,必须要有球也必须要有参与者。服务的这种特性使得SOAD的方法更适合于在系统间建立交互模型,这样通过一个外在的流程引擎就可以通过合理的组织行为的顺序就达成了业务的目标。
从这一点上来看,现在的IT系统存在着大量的冗余。比如开户这个行为,各行各业的业务系统都有,都是不同的实现,但是其实有差异吗?肯定有,但是我要说的是这种差异都是人为造成的,或者说都是系统内部的差异,从外在行为上来看,不都是一个人来到你的柜台或虚拟柜台认证注册一下吗?从行为的抽象角度看,我管你内部是填一张表还是两张表吗?我管你需要多少环节审批吗?其实一旦面向服务的观念被更广泛和深入的认知后,一定会有专业的账户管理机构出现,所有行业的应用需要开户的时候都会直接调用公共的开户服务,这是社会分工的必然趋势。我在这里大胆的预测一下,未来垂直行业的应用提供商一定会逐步消失,取而代之的是各种专业服务提供商+跨行业应用(或服务)提供商。
上图建立了一个理想的云端企业IT模型,其中大部分的应用系统都来自专业的公司提供的公共云服务,企业通过自己的服务建模对云服务进行裁剪,并建立自己可能存在的独特内部应用。然后,通过对内外部的服务能力进行编排组合,从而快速形成自己的业务。
我们都知道,OOAD之所以能成为现今软件界广为接受的一种方法论,有一个关键点在于对象的多态性对系统稳定性带来的好处。
多态性解决了业务流程中不断变化的业务分支产生的代码维护的代价,在面向过程的一段代码中,任何实体发生增加和改变都会导致这段代码需要被修改,于是随着系统的快速膨胀,这种修改变得成本巨大甚至无法承受;而OO的方法巧妙的通过多态性解决了这个问题,所以才会有越来越多的超大系统出现,用于解决更加灵活变化的复杂业务需求。
面向对象的多态主要解决对象实体属性的扩展和操纵方式的差异,也就是说对象属性是不可修改(或重载)但可以增加,对象的方法(操纵方法)可以重载。
那么类似的,S++的方法也希望为跨系统的应用带来稳定性。比如,在传统BPM的一段流程中,任何行为本身发生增加和改变都会导致流程本身的修改,成本也会随着系统的增大而变得不可忍受。
举个例子,通过一个简单的流程去完成查余额然后缴费,传统的BPM需要对所有的缴费方式设立相应的业务分支,一旦有新增的缴费方式出现就必须修改这个流程,增加新的分支;而服务多态性则只需要调用缴费的抽象服务,具体的缴费服务是根据运行时刻的数据由服务的多态性自动完成匹配的。
在服务多态性中,与OO不同的是,由于服务本身就是行为所以没有所谓方法的重载,服务被重载的只有服务对外表达的属性。比如缴费服务中,待缴账号是抽象服务的属性,而被实际服务重载后,就变成电话号码(缴电话费)、水表序号(缴水费)等等实际的行为参与者了。
假如实现了服务的多态性,就可能解决传统的组合流程会随着业务变化而需要修改的问题,从而可能改变传统的业务开发方式,使得大规模使用组合流程引擎开发业务逻辑成为一种可能的选择。
S++通过对传统服务的定义进行扩展,重新定义了 服务 这个最基本的概念,第一个plus加入 业务与技术分离 ,第二个plus加入 服务多态 这两个新的特点。这使得S++继承了SOA和微服务的优点,更进一步的降低了服务的复杂度、提高了服务的抽象度,使得服务更加易于管理和使用。后面我们会看到,基于S++定义衍生出的各种特点在业务和架构层面对传统技术造成的巨大冲击和改进,必然使S++替代传统的SOA和微服务,成为未来企业应用开发和集成技术的主流。
李东,14岁开始学习计算机语言,作为课外兴趣自学了BASIC和汇编,利用放假期间编写了贪吃蛇、打飞碟等游戏。高中、大学期间继续自学软件编程,曾将C和汇编结合使得从高级语言中能够调用绘图功能,并模仿Borland C++开发了一套适合学校机器的图形化开发环境的原型。
93年大学毕业后在西门子合资公司作为交换机软件安装人员工作两年,然后来到JInfonet公司先后参与4GL的研发和JReport的研发。作为JReport的第一代主要研发人员,编写了从原型一直到3.0版本的核心引擎部分。2000年与合伙人一起创建了Bi-Soft公司,主营业务是商业智能软件Bi-Pilot,负责整个产品的研发及管理工作,从最基本的查询一直到多维分析模型和引擎都是产品的涵盖范围。
2007年Bi-Pilot被神州信息收购合并,李东开始在神州信息研发SmartESB产品,用SOA的方法论为客户提供底层产品服务。
感谢郭蕾对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们。