Service-oriented architecture 面向服务的体系结构

什么是SOA

讲在前面的话:
若企业缺乏对服务变更的控制和规则,那么一个服务在经过几个项目之后,就很有可能被随意更改成多个版本,将来变成什么样更是无法预测。久而久之,降低了服务重用的可能性,提高了服务利用的成本。
服务治理在SOA实施之初的作用不明显,甚至在一定程度上影响到项目的进展,但随着SOA实施深入开展和服务数量的增加,其作用会越来越明显。正如SOA架构通过引入了多个层级,在一定程度上牺牲单笔服务调用的效率却换来架构的灵活性一样。

什么是SOA
面向服务的体系结构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约(规范)联系起来。

SOA的定义
面向服务架构,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用。服务层是SOA的基础,可以直接被应用调用,从而有效控制系统中与软件代理交互的人为依赖性。

SOA的优势
对 SOA 的需要来源于需要使业务,让服务变得更加灵活,以适应业务中的改变。更好的实现业务驱动。
SOA具有低耦合性特点,业务伙伴对整个业务系统的影响较低。

SOA的特性
暴露API,可从企业外部访问
随时可用
松散耦合
可重用的服务(与重组服务)
标准化的服务接口
精确定义的服务契约

SOA四大支柱
团队合作
理念共识
纪律规范
范围边界

SOA八个原则
标准化服务合同原则
服务松散耦合原则
服务的抽象原则
服务可重用性原则
服务自治原则(服务合同定义良好功能边界,避免服务重叠)
服务无状态原则?
服务可发现原则
服务可组合原则

服务治理的重要性
服务是SOA的核心。按其愿景,在新项目设计实施过程中,项目团队通常会面临如下问题:
1.企业有无服务目录,服务目录在哪里?
2.哪些服务可在新项目实施中重用?
3.需要新开发哪些功能,这些功能是否要封装成服务,供其他应用使用?
4.当新系统所需要的某一功能已经存在于某一现有系统之中,但是并非以服务形式出现时,是否要对它进行封装,如何封装?
5.服务的调用是否必须经过企业服务总线(ESB、dubbo_zk),何种情况下必须经过ESB,何种情况下不需要?
6.当某个现有服务功能部门满足某项需求时,如何对服务进行改造和版本控制?
7.待开发的新系统是对某个旧系统的升级,那么旧系统提供的服务何时中止,用新系统中的服务替换,还是将服务升级成另一种形式?
8.服务来自于哪个系统,被哪些系统所用?
9.服务由谁负责管理和维护?
10.服务可被哪些人或角色有权限访问?

如何服务治理
1、建立服务仓库
2、制定治理规范
服务定义(服务的范围、接口和边界)
服务部署生命周期(各个生命周期阶段)
服务版本治理(包括兼容性)
服务变更(启用和退役)
服务注册中心(依赖关系)
服务监视(进行问题确定)
服务所有权(企业组织)
服务测试(重复测试)
服务安全(包括可接受的保护范围)

 

 

 

 

 

SOA 面向服务框架设计与实现

由于Java 语言的编译与重启不可抗拒缺陷,所选择使用PHP弥补这个缺陷。

在合适的场景中使用PHP 为 Java 提供 SOA 服务有很多优势,最大的优势就是升级,能够随时升级,即时生效,服务不中断。

 

任何一种语言都有其擅长的一面,多种语言互补是一种趋势。

 

Service-oriented architecture (SOA)

 

 

 

 

 

企业 BPM 与 SOA 如何相互促进 ?

企业BPM和SOA不应该被视为是相互竞争者的两种方法,但是若看作互补的两种法,他们就能相互受益。

企业BPM和SOA的优势是,他们都是组织处理问题的高效解决方案。SOA和BPM不应该被视为是竞争关系,他们是互补的。精炼说,SOA是架构,BPM是业务实践。虽然不同,但二者都能给对方带来极大的好处。

SOA=架构

SOA被定义为“支持服务之间通信的基础结构。”然而,在很多方面它可看作是迷你互联网、是连接电脑的网络,根据特定的查询语句提供不同类别的信息。这些查询可能会启动服务,包括业务规则应用、信息路径或流程模拟运行。SOA本身并不执行这些任务;相反他们的是运行的管道。

BPM=业务实践

另一方面,业务流程管理(BPM)被定义为“系统方法,使组织的工作流更有效、更高效,以及更加有能力适应每一个变化的环境。”需要注意的一件重要的事是,在这个定义中与技术一点关系都没有。企业BPM是业务实践,但却没有人敢大声讲出来,一点也不使用技术来获得BPM成功已经成为可能。也就是说,SOA作为服务商还有很大的发挥空间。

最好的情况下,基于SOA的基础设施和基于BPM的实践一起使用,来达到预期的结果,通常都会超出预期结果。适当地编排,那么采用SOA是改善响应速度、平衡负载、拥抱遗留解决方案的良了的方法。顺便说一下,BPM的更深入目标是帮助者人们工作更有效、更高效、更有能力。

在企业BPM和SOA的讨论中,一些评论人士常常出错的地方是,把SOA支持重大意义业务流程改进的能力与BPM声明达到的结果混淆。SOA能够很好地完成订单,以致于让人误解为它是BPM的代替方案,但要注意这两者服务于不同人士,一是技术的,一是实践的。争论一个好过另一个是片面的,这将给员工以及BPM的时间表和成本造成重大影响。

 

 

微服务与SOA架构

基于服务架构的世界

微服务和SOA都被认为是基于服务的架构,这意味着这两种架构模式都非常强调将“服务”作为其架构中的首要组件,用于实现各种功能(包括业务层面和非业务层面)。微服务和SOA是两种差异很大的架构模式,但是他们仍有一些相同的特征。

所有基于服务的架构的一个共性是他们一般都是分布式架构,也就是服务组件都是通过远程访问协议来实现的,例如REST、SOAP、AMQP、JMS、MSMQ、RMI或者.NET Remoting。相对于单体式架构和分层式架构,分布式架构有很多优势,包括可伸缩性、解耦能力以及对开发、测试和部署的可控性等。分布式架构中的组件更趋向于自包含,因此其变更管理和维护也更容易,从而使得相应的应用也更稳定,响应也更快。分布式架构也非常适用于各模块之间耦合度较低、更加模块化的应用。

在基于服务的架构语境中,“模块化”指的是将应用的各个部分分别封装为自包含的服务的做法。拆分后的每个服务都可以单独设计、开发、测试和部署,与其他组件或服务之间的依赖性很低甚至没有。模块化的架构还支持用重写的方式来维护组件的做法。随着业务增长,架构可以逐渐地、以很小的部件为单位进行重构或者替换,而不是大张旗鼓地对整个应用进行重构或者替换。

不幸的是,凡事都有代价,享受分布式系统的优点也一样。与优点相伴的缺点则是复杂性的增加和投入的增长。维护服务合约、选择正确的远程访问协议、处理不响应的或不可用的服务、加密远程服务和管理分布式事务,这些还只是构造基于服务的架构时许多复杂问题中的一部分。本章中,我会描述这些与基于服务的架构有关的复杂问题。

服务合约

服务合约是服务提供者(通常是远程的)和使用者(客户)之间使用合约语言(XML、JSON、Java Object等)约定数据输入和数据输出的一份协议。创建和维护服务合约是一项困难的工作,不应该被轻视或者当作补充条款。因此,服务合约的议题在基于服务的架构设计中值得特殊关注。

在基于服务的架构中,存在两种服务合约模型可供使用:基于服务的合约和客户驱动的合约。两者之间的真正差别在于合作程度。在基于服务的合约中,服务是合约的唯一拥有者,一般可以在不考虑服务客户需求情况下演化或修改合约。这种模式强迫服务的所有客户都要接受新的服务合约变更,而不管客户是否需要这些新功能。

与之相反,客户驱动的合约所基于的是服务和与服务客户之间更为密切地合作的一种关系。在这种模型下,服务拥有者和客户有很强的合作(关系),因此任何服务合约变更会充分考虑客户的需求。采用这种模型时,服务(拥有者)一般需要了解客户是谁以及每个客户都是如何使用这些服务的。客户可以对服务合约随意提出变更建议,服务方则可以根据是否影响其他客户而自行决定是否采纳。理想情况下,服务的客户向服务拥有者发起修改建议和测试用例,测试被执行时可以监测该修改是否影响其他客户。开源工具如Pact和Pacto可以帮助维护和测试这类客户驱动的合约。

服务合约的上下文中另一个重要议题是合约的版本。我们必须接受这一现实——在服务和服务客户间实现绑定的合约终究是要变化的。改变程度和范围取决于这些变更如何影响每个客户,以及合约改变后服务的向后兼容性。

合约的版本化使得启用新的、包含合约变更的服务功能时能够为仍旧使用老版本合约的客户提供向后兼容性。从开始开发之前就要为合约的版本化做出规划,即使开始你觉得不需要,到了最后一定需要,这也许是本章最重要的一条建议。有很多开源和商业版本的框架可以用来帮助管理和实施合约版本化策略,不过你也可以选择使用两项基本技术来实现自己的合约版本化策略:同质版本化和异质版本化。

同质版本化是指在同一个服务合约中使用合约版本号。图1-1中,被客户A和B同时使用的合约都用圆形(代表同一服务合约)来表现,但是其中各自包含着不同版本号。举一个简单例子,假定合约是基于XML的,用来表示某些商品的订单,采用合约版本号1.0。现在新版本1.1发布了,其中包含了额外字段用于提供当订单派送而接收人不在家的时候的交货规则。这种情况下,可以通过让新的delivery-instructions字段成为可选字段来保持向后兼容版本1.0的合约。

1-1.png


图1-1

异质版本化则涉及对不同类型合约的支持。这个技术跟本节之前描述的客户驱动的合约很相似。服务引入新的功能特性时,就引入新合约用来支持这一(些)功能特性。注意,图1-1与1-2之间不同在于表示服务合约的形状。1-2中,客户A使用圆圈所代表的合约,而客户B则使用三角形所代表的合约。在这种情况下,向后兼容性是由不同合约而不是同一合约的不同版本所支持的。许多基于JMS的消息系统都是采用这种方式,尤其是使用ObjectMessage消息类型的系统。例如,基于Java的接收端可以使用instanceof关键字来检查通过消息发送的对象类型,然后根据对象类型来采取响应的步骤。或者,XML负载可以通过JMS的 TextMessage来发送(每个不同合约包含完全不同的XML schema),由一个消息属性来指明XML schema和XML类型负载之间的对应关系。

1-2.png


图1-2

合约版本化的主要目的就是提供向后兼容性。谨记,服务必须支持多个版本的合约(或者多个合约),这样才能使得开发团队能够更快地部署新的功能特性或者其它变更,而不必担心破坏与其它服务客户之间的现有合约。需要注意的是,这两种技术也可以组合起来,支持不同合约类型的多个版本。

最后一个关于服务合约中变更合约需要注意的是:一定要从开始就制定一个明确的服务客户沟通策略,以便客户能够及时获知合约变更的信息,或者特定合约类型不再被支持的信息。很多情况下,因为内部/外部客户很多,这类沟通并不可行。这时候,一个集成中心(integration hub),或者说消息中间件,可以在服务的客户与服务之间建立抽象层,实行服务合约的转译。我将在后续“合约解耦”一节种谈到这种可能性。

服务可用性

服务可用性(Availability)和服务响应能力(Responsiveness)是基于服务的架构通常需要考虑的另外两个问题。这两者都涉及服务客户与远程服务之间通信的能力,但他们还是有着轻微不同的内涵,因此客户也会采用不同方式来解决这两个问题。

服务可用性是指远程服务及时地接受请求的能力,例如,与此远程服务建立连接。服务响应能力是指客户及时地从服务接收响应的能力。图1-3展示了这种不同。

1-3.png


图1-3

尽管这两种错误条件造成的结果是一样的(服务请求无法被处理),但是处理方式是不同的。因为服务可用性跟服务的可连接性有关,因此客户能够做的并不多,只能要么多试几次,要么在可能的情况下把请求放入队列,以后再处理。

处理服务响应能力问题就更困难一些。请求成功地发送给服务之后,客户需要等待多久?是否服务仅仅是很慢,又或者服务端发生了什么事情导致无法发送响应?解决超时条件问题对于远程服务的可连接性来说是相当具有挑战性的。一种常见的做法是在有负载的情况下获得最长响应时间作为基准,然后在此基础上添加额外的时延以处理负载的波动。例如,假设运行某个基准测试时,某个特定服务请求的最大响应时间为2000毫秒。那么你可能需要将这个值乘以二,用以处理负载较高的状况,因此预期的超时时长应该是4000毫秒。

尽管看起来这是一个合理的估算服务响应超时时长的解决方案,但有时也会有各种问题。首先,如果服务真的停止了或者未启动,每个请求都要等待四秒才能判定服务无响应。这实在是效率太低,而且会引起最终客户的不满意。另外一个问题在于,你所使用的基准测试可能并不精确,在高负载情况下,服务响应时间可能会是五秒而不是我们所算出来的四秒。这种情况下,服务端实际上能够做出响应,但是客户端会因为超时时长设得太低而拒绝了所有响应。

比较常见的一种解决方案是使用断路器模式(circuit breaker pattern)。如果服务不能及时做出响应或者干脆不响应,软件断路器将会起作用,提醒客户不必浪费时间等待超时事件发生。与物理断路器相比,软件断路器很不错的一点是在实现这种设计模式时,可以在服务端开始发送响应或者变得可用时对自己进行重置。软件断路器有不少开源实现,包括Netfix的Ribbon等。你可以在Michael Nygard的书Release It!中读到更多的关于断路器模式的内容。

在处理超时时长值的问题时,应该尽量避免使用全局的超时值来处理每个请求。恰恰相反,建议你基于上下文来定义超时时长,同时确保这些数值可以从外部通过配置来设置,这样你就可以在负载条件变化的情况下快速做出响应,而不用重建或者重新部署应用。另一种方案是在代码中使用“智能超时值(smart timeout values)”,以便在负载变化情况下自行调整超时值。例如,应用可以在高负载或者网络有问题的情况下自动增加超时时长值。当负载降低,响应时间变短后,应用可以重新计算平均响应时间,并对应地降低超时时长值。

安全性

在基于服务架构下,服务都是远程访问的,很重要的一点是需要确认给定的客户是否被授权访问某个特定服务。根据实际情况,服务的客户可能既需要被认证(authentication)也需要被授权(authorization)。认证是指服务客户是否可以连接到某个服务,一般是通过用户名和密码来建立登录凭证来进行认证。某些情况下,仅仅执行认证还不够:客户可以连接到某个服务并不意味着他可以访问服务所提供的所有功能。授权指的是某个服务客户是否被允许访问服务内部特定的业务功能项。

安全在早期SOA实现中是个大问题。原本被严格隔离的某个应用的功能突然被公开,从企业的全球各处都能访问到。这一变化所引发的问题促使我们换个角度思考,重新认识服务以及如何保护服务不会被不该访问的客户访问到。

对微服务而言,安全问题成为挑战主要是因为没有一个专门处理安全问题的中间件组件。相反地,每个服务必须各自处理安全性问题,或者在某些情况下需要增强API层以使之更加智能地处理应用的安全性问题。我看到的微服务中所实现的一个比较好的设计是将认证工作委托给一个独立的服务,而保留授权工作在微服务内部。尽管这一设计可以修改为将认证和授权都交由单独的服务来完成,我还是倾向于将授权包含在微服务自身当中。这样做可以避免与远程安全性服务之间的太多的不必要交互,还可以使得服务的上下文边界更加稳定,减少对外界的依赖。

事务

事务管理在基于服务的架构中也是很大的挑战。大多数时候我们所讨论的事务是指在大量业务应用中都存在的ACID(atomicity、consistency、isolation和durability)事务。ACID事务用于维持数据库一致性,对同一个请求中的多个数据库更新操作进行协调,使得当事务处理过程中发生问题时,该请求所作出的所有数据库更新都可以回滚。

考虑到基于服务的架构一般都是分布式架构,在多个远程服务之间传播和维护事务的上下文很困难。如图1-4所示,一个服务请求(红色X旁边的方框)可能需要调用多个远程服务来完成请求。红色X表明这种情况下无法实现ACID事务。

1-4.png


图1-4

事务问题在SOA架构中更为普遍,因为与微服务架构不同,SOA架构中通常使用多个服务来完成一个业务请求。我将在对比架构特点一章的“服务编排”一节中详细讨论这个问题。

基于服务的架构一般更依赖于 BASE事务,而不是ACID事务。BASE事务一般包括基本的可用性、软性的状态和最终一致性(basic availability、soft state和eventual consistency)。分布式应用依赖BASE事务来追求数据库中的最终一致性而不是每个中间事务的一致性。一个典型的BASE事务的例子是往ATM机里存钱。当通过ATM机向你的账户中存入现金,大概几分钟甚至几个小时后才会在账号中显现出来。换句话说,钱从离开自己的手到真正存入账户之间有一个软性的转换状态:钱已经离手,但是还没到达你的银行账户中。我们可以容忍这一延迟,并且寄希望于软状态和最终一致性,因为我们知道并信任这笔钱最终一定会到达我们的账号。从全系统视图的角度看,批处理作业也是依赖最终一致性的。

迁移到到基于服务的架构需要我们改变对事务和一致性的认识。对于不能依赖最终一致性和软状态的而必需事务一致性的情况,可以将服务的粒度设计得较粗,从而把业务逻辑包装在一个服务内,最后通过ACID事务来实现事务级别的一致性。另一种方法是使用事件驱动技术,当请求状态变得一致时向相关客户推送通知。这种技术给应用带来了很高的复杂度,不过确实能够在使用BASE事务时实现事务状态管理。

太复杂了?

基于服务的架构相对于单体式应用来说是一种巨大的进步,但是正如你所看到的,他们同时也带来很多问题,例如服务合约、可用性、安全性以及事务管理等等。不幸的是,转向基于服务的架构,如微服务或者SOA,意味着必须在某些方面做出权衡。有鉴于此,除非做好准备并且原意去解决分布式系统所面对的种种问题,否则不要匆忙转向基于服务的架构。

本节讨论的问题很复杂,但它们肯定不是不可克服的障碍。大多数使用基于服务的架构的团队最终都能顺利通过开源、商用和定制化的方案解决和克服这些问题。

基于服务的架构是不是太复杂了?肯定是的。但是,事物总是两面的。伴随着复杂性,基于服务的架构也有一些额外的特性和能力,能够提高开发团队的效率,开发出更为可靠的、更为稳定的应用,同时降低总体开销并缩短产品进入市场的周期。接下来的三节中,我会对比微服务和SOA,帮助你了解哪种架构模式更适合自己。

对比服务特性

OASIS面向服务架构参考模型(OASIS Reference Model for Service Oriented Architecture)中将“服务”定义为“一种支持对一或多种能力进行访问的机制,这里的访问是通过使用预定义的接口来提供的,并且稳定地按照服务描述所规定的约束和策略来执行”。换句话说,一个服务要提供某些业务能力,并提供定义良好的接口以及定义良好的合约以便(客户)进行访问。这个定义没有规定的是如何基于类别、组织所有关系以及粒度『如服务的规模』(classification、organizational ownership and granularity)来进一步地定义服务。理解这些服务特性有助于在特定架构模式下为服务的上下文给出定义。

尽管微服务和SOA都有赖于服务作为其主要的架构组件,他们在服务特性上是有很大的差别的。本章将围绕不同模式下服务如何分类(也就是服务的分类学)、如何基于服务的所有者进行服务之间的协调以及微服务与SOA之间服务粒度上的不同展开讨论。

服务分类学

服务分类学指的是在某种架构下服务是如何归类的。有两种服务分类的基本类型:服务类型和业务领域。服务类型分类法会根据整个架构中服务所扮演的角色进行分类。例如,某些服务是实现业务功能的,而另一些服务可能是实现非业务功能的,例如日志、审计和安全。业务领域分类法会根据服务在特定业务功能领域中所扮演的角色来进行分类,例如报表、交易处理和订单送货等等。

服务类型分类一般在架构模式层进行定义,而业务领域分类则在架构实现层进行定义。尽管架构模式提供了很好的基础来定义服务类型,作为一个架构师,你可以按照自己的想法对其进行修改,定义自己的分类方法。本节中,我们会关注架构模式以及在微服务和SOA中比较常见的服务类型。

微服务架构就服务类型而言其分类法并不复杂,一般来说主要有两类服务类型,如图2-1所示。功能服务(functional services)是指用来支持特定业务操作或功能的服务,而基础服务(infrastructure services)则负责支持非业务工作,例如认证、授权、审计、日志和监控。在微服务架构中,这是非常重要的区别,因为基础服务并不对外开放而仅作为供内部使用的私有共享服务,对其它服务可用。功能服务则提供外部访问能力,而且不对其它服务共享。

2-1.png


图2-1

SOA内的服务分类法跟微服务有很大不同。在SOA中,从全局架构来看有非常明确的、非常正式的服务类型,各自在整体架构中扮演不同角色。尽管在SOA中可以有任意数量的服务类型,架构模式定义了四种基本类型,如图2-2所示:

2-2.png


图2-2

业务服务(business services)是一种抽象的、高层级的、粗粒度的服务,定义在企业层面的执行的核心业务操作。因为抽象,所以不依赖于任何实现或者协议,一般只包括服务名字,期望的输入以及期望的输出。可选地,这些服务类型还可以包括处理步骤或者跟服务相关的特殊编排规则。业务服务一般都用XML、Web Services Definition Language(WSDL)或者Business Process Execution Language(BPEL)等语言来表述。一般确认某个服务是否属于业务服务会在服务名上下文前后加上“我们是否在做某某的业务”来加以判断。例如,有两个服务,分别名为ProcessTrade(处理交易)和InsertCustomer(插入客户)。那么“我们是否在做处理交易的业务”可以很清楚看出ProcessTrade是一个业务服务;而“我们是否在处理插入客户的业务”听上去就不对,所以不是一个好的业务服务抽象,更像是一个在处理业务服务时所调用的某个具体服务。

企业服务(enterprise services)是具体的、企业层级的、粗粒度的服务,用以实现业务服务所定义的功能。如图2-2中所示,一般是介于抽象业务服务和对应具体企业服务实现之间的中间件,在其间起到桥梁作用。企业服务可以与业务服务之间存在一对一或一对多的对应关系。
它们可以用任何语言和平台进行定制,或者采用第三方采购的产品(COTS)来实现。企业服务很独特的一点是它们通常会在组织内共享。例如,一个RetrieveCustomer(检索客户)的企业服务可能被组织内很多模块使用,用来接收客户信息。其它例如CheckTradeCompliance(检查交易合规) , CreateCustomer(创建客户), ValidateOrder(验证订单) 和 GetInventory(获取库存目录)等都是企业服务很好的例子。企业服务通常依赖应用服务(application services)和基础服务(infrastructure services)来完成特定业务请求。但是在某些情况下,某个企业服务也可能把完成特定请求所需要的所有业务功能都归入自身,形成自包含的服务。

应用服务(application services)是细粒度的、特定于具体应用的服务,与某个特定应用的语境相关。应用服务提供在企业服务中没有的特定的业务功能。例如,一个大型保险公司汽车报价应用可能提供服务来计算汽车保险费率。这是一个只针对该应用而并不适用于整个企业的服务。应用服务可以从某个专用的用户界面直接调用,或者通过某个企业服务调用。应用服务的例子包括:AddDriver(添加司机)、AddVehicle(添加车辆)以及CalculateAutoQuote(计算机车报价)等等。

SOA中最后一个基本服务类型是基础服务(infrastructure services)。与微服务架构相同,这些服务用于实现非功能性任务,例如审计、安全和日志。在SOA中,基础服务可以从应用服务或者企业服务调用。

需要记住的是,作为一个架构师,你既可以使用架构模式所提供的标准服务类型,也可以完全抛弃他们创建自己的分类方式。不管采用哪种方式,重要的事情是要确保针对架构存在定义良好且文档齐备的服务分类法。

服务责任制与协调

服务责任人(service owner)是组织内负责创建和维护某个服务的组别的类型。因为微服务架构仅支持有限的服务类型(功能服务和基础服务),应用开发团队一般都会同时负责这两种服务。尽管大量应用开发团队可能负责编写服务,需要了解的是他们都属于同一组别类型(即应用开发团队)。图2-3展示了微服务的服务责任制模型。

2-3.png


图2-3

对于SOA而言,一般对不同服务类型有不同服务责任人。业务服务的责任人通常是业务用户,而企业服务的责任人大多是是共享的服务团队或者架构师。应用服务的责任人一般是应用开发团队,基础服务的责任人一般是应用开发团队或者基础服务团队。中间件在SOA架构中经常使用,尽管不是一种服务,其责任人一般是整合架构师或者中间件团队。图2-4展示了SOA架构下服务责任制模型。

2-4.png


图2-4

服务责任人的重要性体现在全局的服务协调。在SOA中,必须在创建或维护某个应用需求的时候在多个组之间进行协调。关于抽象的业务服务必须咨询业务用户,关于完成业务服务功能所需的企业服务必须咨询共享服务团队,应用开发团队之间必须相互协调才能保证企业服务可以调用底层功能。同样,必须协调基础团队来确保非功能性需求能够通过基础服务得到保障。最后,所有这些都需要与中间件团队或者管理消息中间件的整合架构师进行协调。

在微服务场景中,完成某一业务请求通常只需要很少甚至完全不需要对多个服务进行协调。如果需要在多个服务责任人之间进行协调,也可以通过规模较小的应用开发团队快速而高效地完成。

微服务和SOA在服务责任制和总体协调上的不同直接决定了两种架构模式下开发、测试、部署和维护服务上所需要的精力和时间。在这个问题上,微服务模式表现突出。因为服务比较轻量,各个组之间协调最少,服务可以很快被开发、测试、部署。而这些优势最终又转化为较短的投放市场周期、较低的开发和维护成本以及和更稳定的应用。

服务粒度

从服务角度来看微服务和SOA的最大区别在于服务粒度。如名字所示,微服务是规模较小的、细粒度的服务。更确切地说,微服务架构中的服务组件一般都是单一目的/用途的服务,只做一件事且做到极致。而对于SOA而言,服务组件规模相差可以很大,可能是很小的应用服务,也可以是很大的企业服务。实际上,很常见的一种情况是SOA架构中的某个服务组件是由一个很大规模的产品或者一个子系统来提供。

有趣的是,SOA一开始碰到的最大挑战来自于服务粒度。如果不理解服务粒度影响,架构师很可能会设计粒度过细的服务,导致太多信息交互而影响整体性能。架构师和组件设计师很快学习到大规模的、粗粒度的、提供多种数据视图的服务是更好的服务模式。例如,相比较于太细粒度的数据读写服务,像GetCustomerAddress(获得客户地址)、GetCustomerName(获得客户名称)、UpdateCustomerName(更新客户名称)等等,架构师和共享服务团队更愿意采用部署企业级Customer(客户)服务的做法,用于处理更多粗粒度更新和接收数据视图,而把底层数据读写功能委托给并未开放给外部企业的应用级别服务。通过这种方式,像GetCustomerDemographics(获得客户统计数据)或者GetCustomerInformation(获取客户信息)之类的操作会返回一批客户数据,而不是单一的数据字段。

粒度不同自然是跟服务组件的作用范围和功能差异相关。对于微服务而言,服务组件的功能(服务作用范围)倾向于做得较小,有时通过一两个模块就可以完成。对于SOA,服务倾向于包含尽量多的业务功能,有时会作为子系统(例如,索赔处理引擎或者库存系统)来实现。不过,SOA通常依赖于多个服务完成单个服务请求,而微服务却并不这样。我会在下一章的“服务编排”一节中详细讨论这个问题。

无论使用微服务架构还是SOA,选择合适的粒度来设计服务并不是件容易的事情。服务粒度既影响性能也影响事务管理。服务的粒度太细时需要服务间通信来完成单一业务请求,从而导致大量的远程服务请求,占用掉宝贵的时间。假设访问某服务时花在远程访问协议上的时间是100毫秒,如图2-5所示,仅仅花在数据传输上的时间就达到600毫秒。如果将这些服务整合到一个服务中,将会将传输时间减少为200毫秒,这样总处理时间将会减少一半。

2-5.png


图2-5

服务粒度也会影响事务管理。这里我指的是传统的ACID事务,而不是前一章提到的BASE事务。如果远程服务的粒度太细,如图2-6上图所示,就不能使用一个事务工作单位来协调这些服务。然而,如果把这些服务组合进一个较大规模的远程服务中,如图2-6下图所示,这时你就可以用一个事务来协调这些服务,从而确保数据库更新可以在一个事务工作单位内完成。

2-6.png


图2-6

在处理服务粒度时,我发现从粗粒度服务开始会更容易一些。随着对服务的用法的了解逐渐增加,不妨再考虑如何对其进行拆分。如Sam Newman在Building Microservices书中所说,“从少数几个大服务开始”。只需要观察事务问题和服务之间通信量,尤其是在微服务架构下,如果发生相关问题很可能说明服务可能粒度太细了。

粒度与模式选择

本章所描述的三个服务特性中,服务粒度在根据情况进行架构模式选择的过程中具有最重要的潜在影响。微服务中规模很小的、细粒度的服务概念使得这种架构模式能够提升软件开发生命周期中的各个方面,包括开发、测试、部署和维护。尽管采用粗粒度服务肯定会解决性能和事务问题,这一转变反过来肯定也会给开发、测试、部署和维护带来负面影响。如果发现服务规模从小变大,那么最好选择SOA模式而不是更为简单的微服务架构模式。不过,如果能够将应用的业务功能分解为很小的、互相独立的部分,微服务模式应该是更好的选择。

当比较微服务和SOA架构时,除了以上服务特性外,还有很多其他方面需要考虑。下一章中,我们会更多地从全局角度比较这些架构方面,包括每种模式下组件共享水平、服务编排与布置、使用中间件或简单API层以及如何访问远程服务等方面的不同。
 

比较架构特性

组件(component)是软件中的一个单位,具有定义良好的接口、定义良好的角色/责任集合。组件是架构的构成元素。对于基于服务的架构,这些构成元素通常被称为服务(或者服务组件)。不管组件带上什么标签,当创建一个架构时,你都需要决定组件如何被共享、组件间如何通信、多个组件如何被整合起来完成业务请求以及如何从远程服务用户的位置访问他们。

为这些问题做出决定并不是件容易的事情,这就是为什么需要了解架构模式的原因。每种架构模式都有独特的拓扑结构用来定义架构的形状和一般属性,包括组件之间如何相互关联、如何通信、如何协作完成业务请求等等。通过分析架构模式的拓扑结构,你可以更好地决定哪种模式更适合你要开发的应用。
本章我主要分析微服务和SOA之间在总体结构拓扑、架构模式的决定性属性等方面的差异。值得一提的是,这两种架构模式之间的差异主要表现在服务组件的共享程度、服务组件的通信水平以及远程服务组件的典型访问方式。本章也会讨论在SOA架构模式中常见的消息中间件与微服务架构模式中常见的可选API层之间的不同。

组件共享

在组件共享方面,微服务与SOA是有本质上的差异的。SOA是建立在“能共享就共享(share-as-much-as-possible)”的架构风格之上的,而微服务是建立在“能不共享就不共享(share-as-little-as-possible)”的架构风格之上。本节中我会分析这两种概念与其对应的微服务和SOA之间的不同。

组件共享是SOA中的核心概念之一。事实上,组件共享也是企业服务的重中之重。例如,考虑一个大型零售公司,如图3-1所示,有很多应用跟订单处理有关,例如客户管理系统、库存管理系统和订单执行系统。所有这些系统都有自己的Order(订单)服务版本。本例中,假设更新订单的流程需要特殊业务逻辑,这意味着该特殊业务逻辑需要在企业的多个应用之间复制,并且需要应用之间额外的验证和协调。图3-1中还需要注意的是,每个系统都有各自的数据库,因此每个系统中都可能对一个订单有自己的表现形式。

3-1.png


图3-1

SOA期望通过企业级的共享服务(企业服务)来解决这个问题。回到前述的零售案例,假设现在新生成了一个集中共享的Order企业服务,如图3-2所示,更新订单所关联的同一业务逻辑可以被每个应用共享。

3-3.png


图3-2

注意在图3-2中,尽管Order服务是共享的,它仍然在访问三个不同数据库。这在SOA架构采用“能共享就共享”风格时是一个关键概念。Order服务足够智能,知道对不同系统而言需要从哪些数据库检索数据并更新订单数据,同时在三个系统之间同步数据。也就是说,订单并不是通过一个而是三个数据库的组合来完成表述。

尽管“能共享就共享”的架构解决了与业务功能重复相关的问题,但是却带来了组件间耦合过于紧密的问题,增加了与变更相关的整体风险。例如,假设对图3-2中的Order服务做了某个变更,因为Order服务是一个企业服务,对全公司范围可见,很难测试该服务的全部使用场景以确保这次变更不会影响到企业其他部门。

微服务架构,是基于“能不共享就不共享”的理念的,利用了一个领域驱动设计中的概念限定语境(bounded context)。架构上来看,限定语境是指组件(或者这里的服务)与其所关联的数据紧密耦合成一个封闭的单元,与外界有着最小的依赖。这种方式设计的服务组件本质上都是自包含的,只开放定义良好的接口和定义良好的合约。

切合实际地说,即使在微服务架构中也总有某些服务(例如,基础服务)是共享的。然而,SOA架构总是倾向于更大化组件共享,而微服务架构则通过限定语境的概念最小化共享。一种实现限定语境并将依赖最小化的极端方式是违反“不要重复自身(Don’t Repeat Yourself,DRY”原则,将公共性的功能在多个服务中复制,以获得全局上相互独立的效果。另外一个方式是将相对静态的模块编译到共享库中,以便服务组件可以在编译时或者运行时将它们链入。我的好朋友和同事Neal Ford对此有些不同的看法,他认为微服务架构是一种什么都不共享的架构,只有两个例外:一是如何实现服务之间的整合,而是如何夯实基础服务以确保(其它服务)在工程实现上的一致性。

发挥限定语境的概念有很多优点。首先,因为不存在依赖模块,服务的维护变得容易很多,服务的变更和演进都可以相互独立地进行;其次,部署也变得容易很多,需要部署的代码变少,对一个模块的变更也不太可能影响到应用的其它部分。用这种方式生成的应用更加稳定,很少会受到服务变更的副作用影响。

服务编制与编排

服务调配(orchestration)与编排(choreography)之间的区别并总不是很明显。本节中会解析两者之间的区别,以及这两种服务通信概念是如何在SOA和微服务中使用的。

术语服务调配指的是多个服务通过一个集中式调节者进行协调。这里的调节者可以是服务的客户,也可以是一个集成枢纽(Mule、Camel、Spring Integration等)。图3-3展示了服务调配的概念。

3-2.png


图3-3

理解服务调配的最容易的方法就是想象一个管弦乐队的构成。若干音乐家们在不同乐章中使用不同的乐器进行演奏,但他们的演奏都由乐队指挥一个人协调。同样地,服务调配中的协调者组件就扮演着乐队指挥的角色,负责协调所有服务调用以完成业务事务。

服务编排指的则是没有中央协调者的情况下多个服务调用之间的协调。讨论服务编排时,有时会涉及到术语“服务间通信(inter-service communication)”。通过服务编排,某个服务调用另外一个服务,而后者又调用其他服务等等,形成一个服务链(service chaining)。图3-4所展示的就是这个概念。

3-4.png


图3-4

理解服务编排的一种方法就是想象一个在台上表演的舞蹈团。所有舞者都相互同步地移动身位,但是没有人指挥或者指导每个舞者。舞蹈是通过每一个舞者与其他人共同协作实现的,而音乐会则是通过某个指挥的协调来实现的。

微服务架构更适合采用服务编排而不是服务调配,主要是因为这种架构的拓扑结构中没有一个集中式的中间件组件。图3-5所展示的全局架构拓扑中包含两类主要组件:服务组件和(是可选的)非智能化的API层。(我会在下一节讨论API层及其扮演的角色)。从实现的角度来看,架构中还可以有其他组件,例如服务注册和发现组件、服务监控组件和服务部署管理器等等,但是就微服务结构模式的服务分类法而言,它们更应该被视作基础服务。

3-5.png


图3-5

因为微服务架构是一种“能不共享就不共享”的架构,你应该尽量减少服务编排的数量,尽可能让功能服务与基础服务进行交互。如前一章所述,如果发现在功能服务之间需要进行大量的服务编排工作,很有可能是因为你的服务粒度太细了。

在微服务架构中执行太多的服务编排可能会导致出耦合度(efferent coupling)太高的问题。出耦合度这个术语指的是某个组件为了完成某个业务请求在多大程度上需要依赖其它组件。考虑图3-6中的例子,展示了处理订单请求时所需要的三个服务:validate order(验证订单),place order(下单)和notify customer(通知客户)。架构上来说,这个业务请求有很高的出耦合度,而这正是架构师们在采用大多数微服务架构中尽量避免的。

3-6.png


图3-6

服务编排中中发生的服务耦合问题可能引起性能不佳以及应用不稳定的问题。正如前一章所讨论的,因为微服务架构下的服务一般都是远程服务,使用服务编排进行服务协调时所产生的每个服务调用都会延长请求的响应时间,因为远程访问协议的通信传输时间总是存在的。另外,为同一业务请求而对多个服务进行协调时,调用链上的任何一个服务都可能出现不可用或者不响应的状况,从而会导致应用可靠性和稳定性都会下降。

为解决微服务架构中对多个功能服务进行编排的问题,可以考虑将多个细粒度服务合并成一个粗粒度服务。如果某个细粒度服务刚好被另外几个服务共享,那么可以保持它独立。或者,也可以根据此功能的规模及自身属性,有意违反DRY原则,将这一共享功能复制到每个粗粒度服务中。

图3-7中展示的是如何通过将三个细粒度服务整合为一个粗粒度服务,消除服务编排从而解决与服务编排相关的问题。这里所指的问题具体包括:首先,因为减少了远程调用,整体的性能会得到提升;第二,因为服务可用性的问题出现得更少,整体的稳定性得以改进;最后,因为不再需要远程服务合约,总体上的部署和维护得以简化。

3-7.png


图3-7

SOA,作为一种“能共享就共享”的架构,同时依靠服务调配和编排来完成业务请求的处理。如图3-8所示,SOA中的消息中间件,通过调用多个企业服务来处理同一业务服务请求,从而完成服务调配。一旦加入到企业服务中,服务编制组件可以用于调用应用服务或者基础服务来帮助完成特定业务请求。

3-8.png


图3-8

图3-8展示了SOA架构中使用服务编排的几种变化形式。例如,企业服务可能需要调用应用服务,而此应用服务又需要调用一个基础服务完成业务处理。另一种情况是,企业服务也可能只需要调用一个应用服务或者一个基础服务。还有可能业务逻辑直接自包含在企业服务中而不需要任何服务编排。

微服务和SOA在服务调配和编排方面的不同,进一步说明二种模式在架构特征方面存在诸多差异,包括性能、开发、测试和部署等等。因为SOA一般依赖多个服务(和服务类型)来完成同一业务请求,基于SOA架构构造的系统一般比微服务慢,而且需要更多时间和精力进行开发、测试、部署和维护。实际上,这也是让架构师慢慢从SOA转向更为简单和直接的微服务架构的部分原因。

中间件与API层

如果比较前一节中的图3-5和3-8,你就会注意到两种架构模式中都存在一个中间件组件来执行调度。然而,事情并不是这样的。微服务架构模式中通常包含一个称作“API层”的组件,而SOA中所包含的是消息中间件组件。本节中我们会比较这两种组件所扮演的角色和所提供的能力。

微服务模式不支持消息中间件(例如,集成枢纽或者企业服务总线)的概念,而是支持在所有服务的前端设置一个API层作为服务接入层。在客户和服务之间放置一个API层通常是个不错的主意,因为这个组件实质上构造了一个抽象层,使得客户不需要知道服务端的确切位置。同时也使得服务粒度的改变不会影响到服务客户。对服务粒度进行抽象的确需要在API层提供一定的智能和一定程度的调配能力,但这些问题可以慢慢通过重构解决,重要的是服务端可以根据需要演化,而不是要求服务的客户也经常做出变更。

例如,假设有个服务跟产品订单业务功能有关。我们发现它的粒度太粗了,想把它分解成两个粒度更细的服务,从而提高服务的伸缩能力并简化部署。如果没有API层来为实际的服务端提供抽象,使用该服务的每个客户都要做出变更,从调用一个服务转为调用两个服务。如果使用了API层,服务的客户端就不需要知道(甚至不在乎)同一请求现在将被分解成两个服务调用。

SOA依赖于其消息中间件来协调服务调用。使用消息中间件(我更愿意称为集成枢纽)可以获得一些在微服务架构风格中不存在的额外的架构特性,包括调解和路由、消息增强、消息转换和协议转换等。

调解和路由(mediation and routing)指的是架构基于特定业务或者用户请求来对服务进行定位和调用的能力。这种能力如图3-9所示。注意本图中对服务注册或服务发现组件的使用,以及对服务调配能力的利用。微服务和SOA都有这种能力,特别是服务注册或者服务发现模块所提供的能力。不过,服务调配在微服务中被严格控制甚至排除,而在SOA中却是经常用到的能力。

3-9.png


图3-9

消息增强(message enhancement)指的是架构在请求的数据部分到达服务之前之前对其进行修改、删除或者增加的能力。消息增强的例子包括改变日期格式、添加额外数值或者查询数据库进行数据转换,例如将统一安全鉴定程序委员会(Committee on Uniform Security Identification Procedures,CUSIP)代码转换为股票代码或者从后者转换为前者。微服务模式不提供这种能力,主要是因为其架构中不包含实现这一功能的中间件组件。SOA通过其消息中间件完全支持这种能力。

图3-10展示了这种能力。注意,图中客户所发送的是CUSIP代码(一种标准交易标识码)和格式为MM/DD/YY的日期数据,而服务期望接收的是证券交易所每日正式牌价表(Stock Exchange Daily Official List,SEDOL)代码(另外一种交易标识码)以及格式为YYYY.MM.DD的日期以及股票代码(假设是股票交易)。本例中,消息中间件将CUSIP代码(苹果公司是037833100)转化为SEDOL数(苹果公司是2046251),查询并添加代码(AAPL),将日期从04/23/15转化为2015.04.23。

3-10.png


图3-10

消息转换(message transformation)指的是架构将一种数据格式转换为另外一种格式的能力。例如,如图3-11所示,客户调用服务并以JSON格式发送数据,而服务期望接收的是Java对象。注意消息增强『译注:似应为消息转换』并不关心请求相关的数据本身,而只是关注数据格式的转换。微服务架构并不提供这种能力,而SOA架构则通过消息中间件提供这种功能。

3-11.png


图3-11

最后,协议转换(protocol transformation)所描述的是架构允许客户采用与服务端预期不匹配的协议来调用服务的能力。图3-12展示了这种能力。注意,图中服务客户采用REST进行通信,但是负责处理请求的服务要求建立RMI/IIOP链接(例如,Enterprise JavaBeans 3 [EJB3])和AMQP连接。微服务可以支持多种协议类型,但是服务的客户和服务必须采用同一通信协议。在SOA架构中,多个协议则可以根据需要混合使用。

3-12.png


图3-12

我会在下一章中详细讨论这些能力,因为它们跟微服务和SOA的架构能力比较更相关。

访问远程服务

由于微服务或者SOA架构中服务通常是远程访问的,这些架构模式都需要提供一种供客户访问远程服务的方式。就远程访问而言,两种架构模式的根本差别在于,微服务倾向于把REST作为首选远程访问协议,而SOA则没有这种限制。事实上,可以同时处理多种不同远程访问协议是SOA与微服务架构相较最关键的不同点之一。

微服务有一个基本原则是技术和架构选项非常受限,这也使得该架构模式比较简单。例如,大多数微服务架构都仅使用两种访问协议:REST和简单消息(JMS、MSMQ、AMQP等)协议。这并不是说,不能采用其他远程协议,例如SOAP或者.NET Remoting,而仅仅是说一般微服务都倾向于选用同质协议。换句话说,服务要么是基于REST的,要么基于消息的,要么是基于其他协议的,但是在同一应用或者系统内是很少会混合使用多种协议。一个例外也就是可能出现混合使用协议的状况是,依赖发布订阅(publish-and-subscribe)广播模式的服务可能是基于消息的,而其他非广播式服务都是基于REST的。

SOA则没有对架构模式中采用哪种远程访问协议进行限制。在下一章中可以看到,架构中的中间件组件能够支持任意数量的远程访问协议,并提供各种协议之间的转换。尽管如此,大部分SOA架构通常依赖于消息(例如JMS、AMQP、MSMQ)协议 SOAP作为主要的远程访问协议。根据SOA架构范围和规模,在异构服务之间使用六七种远程访问协议的情形也并不少见。

比较架构能力

上一章中我们讨论了架构模式如何帮助确定基本的架构特性。本章中,我们采用类似方法,集中讨论架构模式所描述的架构能力而不是架构特性。通过分析架构模式,你可以判定应用是否易伸缩、易维护和易扩展,以及是否相对地易于开发、测试和部署。

本章中,会对微服务和SOA的架构能力进行集中讨论,主要包括三个方面:每种架构模式所能支持的最大应用规模、使用每种架构模式可以集成的系统和组件类型以及架构模式支持合约解耦的能力。

应用范围

应用范围是指某种架构可以支持的应用的总体规模。例如,微内核或者管道架构更适合较小的应用或者子系统,而其他模式如事件驱动的架构则适合于大型、更复杂应用。那么在这个谱系中微服务和SOA模式适合哪种规模的应用呢?

SOA更适合大型、复杂的、企业级系统,一般都需要整合很多异构应用和服务。也比较适合有很多共享组件的应用,特别是包含全企业内共享组件的应用。因此,SOA更适合于大型保险公司,因为这类企业内部有很多异构的系统环境,并且需要在多个应用和系统之间共享很多公共服务,如:客户、索赔和策略等等。

然而,对于拥有很多定义良好的处理工作流的基于流程的应用(例如证券交易)而言,因为没有很多共享组件,用SOA实现起来比较困难。小的、基于web的应用也不太适合SOA因为不要大量的服务术语、不需要抽象层或消息中间件。

微服务模式更适合于小型的、功能划分明确的基于web的系统而不是大规模企业级系统。使之不适合大规模复杂业务应用环境的最主要原因之一就是架构中没有一个协调者(消息中间件)。适合微服务架构模式的另外一些应用的例子是共享组件很少以及以及可以划分为更小的操作模块的应用。

某些场合中你会发现微服务架构是业务开始时很好的架构选择。随着业务成长变得成熟时,会开始需要对复杂请求进行转换的能力、实时复杂调配的能力和整合异构系统的能力。这时,你很可能会用SOA架构模式替代初始的微服务架构。当然,反之亦然。你也可能最开始设计的是复杂的、大规模的SOA架构,在后来意识到其实并不需要SOA架构的所有的强大能力。这时候,你很可能又会希望从SOA架构迁移到微服务,以简化系统架构。

异构互操作

异构可互操作性(heterogeneous interoperability)指的是与用不同语言和平台实现的系统进行集成的能力。例如,可能出现的一种场景是对同一复杂业务请求的处理需要协调一个基于Java应用,一个.NET应用和一个客户信息控制系统(Customer Information Control System,CICS)的COBOL程序。其他例子还有,比如用.NET平台实现的一个交易系统需要访问一个AS400平台完成股票交易的合规检查;某个基于Java的零售商店需要与一个大型的第三方.NET数据仓库系统相集成。

这些例子在大公司中随处可见。许多银行与保险系统仍然有大量后台核心处理采用COBOL大机应用,而这些应用需要被现代的基于Web的平台访问。整合多个异构系统和服务的能力微服务架构与SOA相比稍显薄弱的地方之一。

微服务架构风格试图通过减少服务集成的选项来简化架构模式和相关实现。REST和简单消息机制是最长用到的两个主要远程访问协议。SOA则对异构协议的使用没有约束甚或通过消息中间件来促进了异构协议的多样化。

微服务架构风格支持协议感知异构互操作(protocol-aware heterogeneous interoperability)。如果具备了协议感知的异构互操作性,就意味着架构可以支持多种远程访问协议,但是特定客户和与所访问的服务之间必须使用同一协议(例如,REST)。如图4-1所示,事实上,了解服务客户与服务之间所采用的远程访问协议并不意味着就了解任何一方是如何实现的,也不意味着双方在实现上要保持一致。例如,通过REST,服务客户可以很容易地在.NET上用C#实现出来;而服务自身则可以通过Java实现。不过,对于微服务而言,客户端与服务端在协议上必须一致,因为二者之间没有中间件组件进行协议转换。

4-1.png


图4-1

SOA也支持协议感知的异构互操作能力,但是它支持得更进一步,可以做到协议无关的异构互操作能力。具备协议无关的异构互操作能力意味着服务的消费者不但不关心服务端如何实现而且也不关心服务端在采用哪种协议进行侦听。例如,如图4-2所示,在.NET平台上用C#实现的某个服务客户端可以使用REST调用对应的服务,但是服务(本例中是EJB3 Bean)只能使用RMI通信。能够将客户协议转移为服务协议的能力称作叫协议转换,是通过使用中间件组件来实现的。再重复一次,因为微服务架构没有消息中间件组件的概念,也就不支持协议无关的异构互操作能力。

4-2.png


图4-2

如果你发现自己所处的是异构环境,需要对多种使用不同协议的系统或者服务进行整合,那么很可能需要采用SOA架构而不是微服务架构。反过来,如果所有服务都可以通过同样远程访问协议(例如,REST)提供给客户访问,那么微服务应该是正确的选择。不论哪种情况,在选择架构模式之前,都需要充分了解互操作性需求。

合约解耦

合约解耦(contract decoupling)可以认为是抽象的最高境界。合约解耦的本质含义是允许服务客户用不同于服务所期望的消息格式与之通信。

合约解耦是一种强大的能力,能够为服务客户和服务之间提供最大程度的解耦。这种能力允许服务和服务客户之间相互独立地演化,同时仍然在彼此之间维护着合约。这种能力也使得服务客户有能力通过客户驱动的合约来推动合约变更,从而在服务客户和服务之间建立一种更加密切的合作关系。

合约解耦的形式主要有两种:消息转换和消息增强。消息转换只关注消息格式而不是请求数据本身。例如,一个服务可能要求消息请求以XML作为输入格式,但是某个服务客户决定发送JSON数据。这种转换工作比较直接,可以使用大多数开源的集成枢纽软件来处理,包括Apache Camel、Mule和Spring Integration等等。

当服务客户所发送的数据跟服务所期望的不同时,事情就会变得比较麻烦。实际合约数据中的失配可以通过消息增强能力来解决。消息转化关心的是请求数据的格式,消息增强则关注的是数据本身。消息增强能力允许组件(一般是中间件组件)添加或者改变请求数据,从而使得服务客户所发送的数据复合服务的期望。

考虑这样一个场景,客户为执行简单股票交易以JSON对象的格式发送数据。服务客户通过发送客户ID、CUSIP代码来指定对哪只股票执行操作、要操作多少股,最后是MM/DD/YY格式的交易日期。


{"trade": {
"cust_id": "12345",
"cusip": "037833100",
"shares": "1000",
"trade_dt": "10/12/15"
}}   


而服务本身期望接收的是XML格式数据,其中包括账户号、股票代码、交易股数以及格式为YYYY.MM.DD的日期。


<trade>
<acct>321109</acct>
<symbol>AAPL</symbol>
<shares>1000</shares>
<date>2015-10-12</date>
</trade>


如果客户和服务之间在合约格式上出现分歧,一般需要依靠消息中间件或者定制的客户适配器来执行必要数据转换以及数据查询功能使得不同合约之间能够平滑工作。图4-3给出了一个这样的例子。数据库或者缓存查询可以基于customer ID得到账户号,基于CUSIP代码的股票号码。日期可以被转换成不同格式,交易股数则可以不做转换地拷贝到新的数据结构。通过转换,可以允许客户采用与服务不同的协约,当发生合约变更发生时,消息中间件可以屏蔽这些差异。

4-3.png


图4-3

合约解耦显然有一些使用上的局限。如果服务所需数据无法从客户所发送数据转换获得也无法从其它数据源获得,服务调用只能返回失败,因为服务合约无法得到满足。幸运的是,服务客户与服务之间的协议分歧大多数时候可以通过查询能力和基本的转换(例如日期,时间和数字域)来予以弥补。

现在IT业界碰到 一个问题是如何防止技术(IT部门)驱动业务。无论是升级一个大规模子系统的软件版本还是替换财务或客户管理系统,都可以通过合约解耦来实现接口和合约抽象,进而使得IT部门的技术变更不会影响到企业的业务应用。之前的股票交易场景是一个很好的例子。将使用CUSIP代码的交易平台替换为使用SEDOL代码的平台并不意味着企业的所有业务应用都需要改成使用SEDOL代码。

不幸的是,微服务在这一架构上又输给了SOA。微服务架构不支持合约解耦,而合约解耦是SOA架构所提供的主要能力之一。如果你自己的架构中需要这种层次的抽象化,那么最好为自己的应用或系统选择SOA解决方案而不是微服务。

总结

微服务架构模式是IT行业正在升起的明星。尽管微服务模式解决了大规模单体式应用和复杂SOA架构下的很多问题,但是它的确也缺少某些SOA提供的核心能力,包括合约解耦和协议无关的异构互操作性。

需要记住的一个基础概念是,微服务架构是“能不共享则不共享”的架构模式,非常强调限定语境,而SOA是“能共享则共享”的架构模式,侧重抽象和业务功能的重用。通过理解这一基本概念以及微服务与SOA的其它特点、能力与不足,就可以在做架构选择时有更明确的判定标准。

如果了解更多微服务和SOA以及分布式架构,可以参看Neal Ford和Mark Richards的Service-Based Architectures: Structure, Engineering Practices, and Migration

如果想深入了解微服务,建议参考Sam Newman的书: Building Microservices(O'Reilly)。

最后,如果想了解微服务和SOA等基于服务的架构中所涉及的消息技术,可以参看 Enterprise Messaging: JMS 1.1 and JMS 2.0 Fundamentals (O'Reilly video)和 Enterprise Messaging: Advanced Topics and Spring JMS(O'Reilly video)。

 

 

 

 

 

 

SOA架构设计经验分享—架构、职责、数据一致性

1. 背景介绍

 

最近一段时间都在做系统分析和设计工作,面对的业务是典型的重量级企业应用方向。突然发现很多以往觉得很简单的问题变得没有想象的那么容易,最大的问题就是职责如何分配。论系统架构设计的最大的问题,其实也就是职责的分配,分配的合理,实现起来就会很柔性,反之就会使架构很混乱。

 

软件的生命周期大概可以归纳为四个基本的过程,分析、设计、实现、测试,当然这仅仅是一个最为粗略的表示而已。不同的方法论有着不同的使用这几个过程的方式。RUP使用快速迭代的过程,在这个几个子过程中适当的输出一些过程制品,每次迭代都是进行相同的分析、设计、实现、测试。而在Scrum中,不提倡输出任何文档形式的过程制品,也同样有着上述几个过程,强调以人为中心,通过沟通来解决大部分的问题。

 

不能用好与不好来判断哪一种方法论,只能根据目前的实际情况综合权衡。RUP的每次迭代中有几个关键的制品对系统分析、设计很重要,可以说是非常重要,如:词汇表、业务规则文档、用例、领域草图。这几个制品对分析、设计很重要,需要从这几个制品中提炼出设计模型最终才能落地。这主要用在业务复杂的应用系统中。而Scrum更加的轻量级,可以用在互联网项目中,业务不是太复杂的情况下。

 

其实我为什么要强调软件工程及开发方法论,是因为我最近发现,做设计其实是建立在分析的基础上的,但是这里面又有很多问题。大型企业级应用,并不能通过一次性分析就可以得出准确和全部的需求,初期阶段建立的需求70%都是不准确的。所以做架构需要有分析的能力才行且是建立在适当的开发方论上的分析,什么时候该用RUP,什么时候该用Scrum,什么时候该用XP都很有讲究。分析与设计都需要有一个执行上下文,不同的上下文对分析、设计的执行有着不同的要求。

 

有句话我觉得对架构者来说很有启发:分析就是做正确的事,设计就是正确的做事。架构跟语言跟平台关系不大,毕竟架构是设计过程中的子过程,我想如果你的设计不合理,你用任何语言任何平台都解决不了问题。(这里的架构上下文指:企业应用架构不是基础设施的系统架构)

 

2. SOA的架构层次

 

进行SOA类型的架构设计就需要搞清楚SOA架构模型才行。并不能想当然的对系统进行简单的拆分就行,需要搞清楚SOA的架构模型是怎样的,每一块是干什么用的,这样设计由分析阶段输出的需求时才能正确的划分职责。

 

如果把SOA的架构简单的理解为是多个子系统之间的整合其实有点太过于简单,也没有真正搞清楚SOA的架构模型。按照SOA的正确方法论及目标模型,其实SOA在实现架构落地上,需要考虑到对服务的组合,不断的重用现有的服务,让企业应用可以逐步集成,快速实现业务的迭代。其实这就是本节要讲的服务的分层,通过分层将服务按照使用类型进行分配,上层服务对下层服务的包装,下层服务负责原子性的操作,上层服务对下层服务进行业务性的组合。

 

我们来看具体的每一层的作用及主要职责。

 

2.1.应用服务(原子服务)

 

应用服务就是诸如:订单服务、仓库服务、销售服务、客户管理服务,这些服务直接对应不同的应用系统,直接服务这些应用系统的原子操作。订单服务直接原子性的插入订单,没有任何跨其他服务的分支逻辑。仓库服务只管自己的仓库逻辑。同样其他的应用服务只管好自己的职责,杜绝对其他服务的调用。

 

图1:

 

应用服务位于UI与后台之间,后台我们可以认为它是一异构的系统或者是数据库之类的。应用服务的位置位于前端与后端之间,起到类似一个服务API的作用,但是SOA中的服务还远远不止这一个应用服务,如果我们的SOA架构中只有一种类型的服务,那么这会增加我们系统的耦合程度,因为你没有对系统的服务进行层次的划分,你的业务功能会直接的落到某一个应用线上的服务,继续往下看。

 

2.2.组合服务

 

组合服务是对应用服务的一个组合,根据实际项目的规模大小,不一定非要进行物理的隔离,在代码层面的服务化也是可以的,在将来的某一天有必要的情况下再进行物理的拆分,毕竟物理的拆分有着严重的成本和代价,对系统的稳定性带来很多挑战。所以经验告诉我们必要的时候在进行拆分。”分布式系统设计的第一个原则就是尽量不要分布式“,这是马丁.福勒大师说的,现在理解确实感同身受。

 

图2:

 

组合服务对下层的应用服务进行了组合,完成了一个基本的业务动作,应用服务中是最基本的基础性的原子性的操作。但是在复杂的业务需求下大部分业务功能都需要跨越多个应用线来完成一个最外层的企业动作。提交订单可能需要穿过很多应用线,订单管理、仓库、财务等等环节。所以这里我们还需要一个能在最外层对组合服务进行编排的业务服务。这个编排服务可以完全是自动化的,通过工作流引擎进行组合自动化来完成,这对企业应用的自动化流程很有意义。

 

2.3.业务服务(编排服务)

 

业务服务是最外层的服务,向下编排了组合服务。业务服务位于最上层,当需要有跨越多个应用线来完成的业务,这个业务就放入业务服务中。比如提交订单,先检查库存、扣减库存(冻结库存),然后下单,再往后通知财务,再往后通知物流等等都是一个复杂的企业服务线。这种最外层的业务逻辑如果你不进行SOA分层然后将其放入最外层的业务服务中,你把它放入任何一个应用线都会使系统调用混乱不堪。所以问题就是需要进行纵向的划分层次。如果进行了SOA的层次划分后就不会出现互相乱用的情况。其实这里可以参考阿里的服务设计方法。(李智慧写的一本大型互联网架构与实践里面也讲到了服务要划分层次)

 

图3:

 

当在业务服务中执行的业务逻辑时,需要跨越多个应用线来完成。这部分的逻辑也说是职责,如果不放入这个位置,放在哪个应用线都不合适,放入哪个应用线都会使系统调用出现混乱。其实这里的问题就是我们不能用一个维度来进行SOA系统的设计,本来服务就具有组合特性,所以适当的提升服务的层次是有好处的,但是应用服务和组合服务可以在代码层面上进行构建,而业务服务也叫编排服务是需要进行物理隔离的,毕竟考虑到系统复杂度和稳定性问题这是值得的。在排查问题,系统性能、稳定性等等方面,物理的隔离有一定的作用,毕竟业务服务本来就是来组合多个应用线的,这样做会使整个系统架构很清晰。

 

3. SOA化的重构

 

进行SOA化的实施,大部分情况下都是对现有系统进行重构后考虑的,初期企业发展阶段以快速出原形为首要目标,只有当系统出现瓶颈了才会考虑运用SOA来解决。但是在这个时候有很多历史包袱无法解决,进行SOA化的重构其实成本是很高的,而且很危险,对有些复杂的逻辑说的现实点,是无能为力的。如果都可以通过重构这个技术来解决,那我们就太天真了。《重构—马丁.福勒》一书讲的是代码层面的重构,跟做系统级重构两个概念。对系统级别的重构还没有太多成熟的方法论支撑。尤其现在新技术层出不穷的,各有优点,能很好的运用这些技术、方法论、过程来重构大型企业级系统,难度非常大,这需要整个公司投入很多人力、资源成本。回过头来想想,其实在前期适当考虑一下还是有必要的,这样可以减少后期很多技术债务。

 

这里我只总结我在分析、设计公司某一块业务系统的时候对其进行SOA化的重构思路。重构本来就是一个不断迭代的过程,不可以跨大步。通过很多脚手架支撑,让系统慢慢的过度到新的SOA架构下,既然要实施SOA架构,那么很重要的一点就是对迁移的业务逻辑适当的归类,什么业务逻辑该放入“业务服务”中,什么逻辑该在代码层面上放入“组合服务”中,对基本的操作有如何放入代码层面的“应用服务”中。

 

3.1.保留服务空间,为了将来服务的组合

 

在进行系统拆分的时候,对当前后端的调用都进行适当的规划,将其分为两类,一类是应用服务,一类是组合服务,这两个服务是可以在代码层面上进行抽象。重点是那些调用其他系统的地方,需要将其放入业务服务中,这块逻辑比较复杂,难以抽取,需要适当的结合”数据落地“的思路来综合考虑。有时候把一部分数据落入本地可以提升系统的整体简洁度和稳定性,但是要考虑数据的一个生命周期性质。

 

在迁移的过程中可能还会有一些新的功能并行开发的,既有新的逻辑需要放入新的SOA服务中,也会有迁移过来的逻辑,这两个过程同时进行其实很痛苦,尽量避免这样同时进行,但是现实是根本不可能,正常都是一起并行推进。如果这两个过程是同一组团队负责其实还好,毕竟对这块的代码、业务都比较了解。

 

这一节目的是想强调对现在系统进行迁移的时候要考虑服务的层次,不要只进行一个简单的搬移代码,这个时候是一个对代码进行重构的好机会,该划分层次的要划分层次,该读写分离的要读写分离,要重点考虑那些“业务服务”,需要跨越多个应用线的逻辑。

 

顺便说一下,还有一个重点就是迁移的时候还要考虑数据存储方面的迁移,光代码层面的迁移只是第一步,第二步还需要进行数据层面的迁移。当然这两个大的步骤都是要通过很多次迭代完成,并且还是一个对业务、代码进行很好梳理和整理的好机会。

 

在将系统进行服务化的时候要考虑服务层,如果当前没有业务服务的逻辑那么就保留服务空间,至少要清楚在服务层中有这么一个空间是要预留的,当有其他的应用线需要与你交互的时候可以顺利的进入到你的服务区,而不是直接到达你的应用。

 

4. 运用DDD+GRASP进行分析和设计(防止主观的判断导致错误的假设)

 

做系统设计时最怕的就是职责搞错了,这会使系统的架构突然就复杂了,而且系统架构都是很难改变的或者压根就无法改变的决定。所以我对这块引起了重视,有时候你对业务在了解在熟悉依然会搞错职责,对于这块光凭主观的判断是不长远的,无发复制、无法传播的,也无法落字成文的。

 

对DDD我这里就不多做介绍了,这里要强调是GRASP。运用DDD可以很好的帮助我们来战略性的观察企业所坐立的领域,我还是很提倡DDD在公司实施的,不说DDD中的“战术设计”方法论,就光说它的“战略设计”方法论还是有很大作用的,让我们可以在脑海中建立一个战略性的模型。具体要不要进行代码层面的落地这就看实际情况了。而且DDD中的很多不错的思想都可以借鉴过来,包括领域通用语言,有了领域通用语言团队之间的沟通和交流会节省很多成本。对于新人来说,可以很快的了解公司的一些大概的业务,这和“词汇表”其实还是有区别的。

 

上面说了,在划分职责的时候很多都是通过经验来主观的判断,没有其他的客观证据了。那么有没有一个不错的方法论或模式来指导我们进行这类问题的解决呢,其实还是有的,因为在国外人家这方面已经很成熟。

 

GRASP就是这样的一套模式,它可以帮助我们进行客观的设计职责。到底该把这块数据放入哪个应用中,到底该把这个逻辑放入哪个服务中,都有指导,包括对对象层面的设计依然可以。我们可能对“信息专家模式”都有了解,但是以往我们可能都只把它用在对象设计上,而没有提升一个系统层面中考虑。那是因为我们以往可能没有碰见很复杂的职责分配场景,只有当出现问题时我们才能真正领会某个东西的好坏。

 

DDD只有结合GRASP才能客观准确的方配某个领域的职责,不管是战略设计层面还是战术设计层面,都是一个很好的平衡标准,不会由于技术人员主观的兴趣倾向导致一个错误的职责分配决定,而这个错误的决定最终是要开发人员来买单。

 

5.SOA分布式下的数据一致性

 

传统分布式系统与当代的面向SOA的分布式系统有一定区别,论概念上来讲SOA是以服务为中心,既然以服务为中心就会有很多面向服务的设计原则。而传统的分布式系统没有服务的概念,也没有所谓的一切皆是服务的原则。而当代SOA则首要原则就要以服务为中心,针对服务的设计又有了很多服务设计原则。

 

SOA对服务还进行了类型的划分,按照服务的应用层次来分类:业务服务、组合服务、应用服务,包装服务等。再按照管理与运维的层面来分类:控制服务、调度服务、监控服务等等。传统的分布式系统是没有这些的,我们谈论的是当代SOA的分布式系统,所以我们强调的是以服务为中心,以服务设计原则为架构设计的指导要求,当代SOA是对传统分布式系统的一个迭代进化,不是一个时代的产物,SOA更加强调了以服务为首要原则,已经提升到了另外一个更加高级的层面。

 

本节我们交流一下在当代SOA分布式系统中的数据一致性问题,在SOA中这主要涉及两个层面来考虑,一个是服务层面、一个数据持久化层面。再按照一致性的基本要求,可以分为:读一致性、写一致性、会话一致性、最终一致性、实时一致性等几个维度,当然还有其他几个维度的一致性要求。

 

我们这里重点讨论在企业应用中实施SOA时遇到的一些比较棘手的数据一致性问题和解决方案,对于刚才提到的几个维度的一致性要求均具有重要的参考价值。

 

5.1.分布式事务(基于DTC的分布式事务)

 

以往包括目前很多项目还是倾向于使用DTC来处理分布式事务,这个方案多数适用于一般的企业应用,业务、访问量、数据量要求都不是很高的情况下。用DTC很方便,事务的自动传播、事务的自动感知、事务的自动回滚和提交,这都是中央DTC帮我们管理好了。

 

由于有中央DTC的统一协调,看似好像帮我们解决了很多我们需要考虑的问题,但是它也是整个平台的致命的瓶颈,一旦DTC由于某个问题出现错误,而且这种错误都是系统层面的错误,很多问题我们是无能为力的。如果出现问题,整个应用平台都无法完成任何一个跨服务的业务流程,这其实很危险,你不无法控制系统的稳定性。

 

这里总结,DTC用于一般的小型企业应用,不建议用在中等规模的企业应用中,不是说这个东西不好,而是无法控制它。

 

5.2.事务补偿(提供正向或反向的操作来让数据在业务上是一致的)

 

世界级SOA专家所编写的书籍里都提到了使用“补偿”操作来完成数据的不一致性,当我们编写了一个服务方法A,就需要一个服务方法A1的补偿接口来完成A服务的补偿操作。但是真实的业务情况下很难实施这种看起来好像很优美很柔性的设计。没有实践就没有发言权,我们公司的技术团队就实施过这种方案,但是很不理想,这跟技术本身及技术团队没关系,只是我们的平台业务太复杂,很难去“补偿”一个已经做过的操作。

 

这当然也要看你所面对的项目情况,量变引起质变,如果你的各种量都上去了,这个“补偿”方案不实际,而且很难在数据层面进行“补偿“。总之,这不是一个中长期的方案。

 

5.3.异步EDA(基于异步事件流来实现柔性的分布式事务)

 

EDA简称”事件驱动架构“。多个系统之间通过传播”事件“来驱动整个业务的运转。系统之间没有紧耦合的同步调用的操作,都是通过发出异步的“事件”来通知下一个业务环节。

 

可能你会有一个疑问,异步操作,是不是系统之间延迟会很长,其实不是,现在有很多成熟的消息中间件在内网内几乎是毫秒级别的延迟,至于跨机房就看物理上的距离了。

 

异步操作有很多好处,这里我就不浪费大家时间重复那些好处。使用EDA实现系统之间的一个松散的事务关系,要把控好项目的质量,对系统的非功能需求、BUG数等等可能会影响业务操作中断的地方都要建立起适当的机制,让这些问题尽早的在线下解决。比如可以实施UnitTest、持续集成等一些敏捷的方法论。

 

6. 总结

 

同样一个工具在于什么人用,真正的工匠都是使用很朴实的工具来雕刻无法超越的艺术品,这就是工匠情怀。最近对工匠情怀感受越来越深,一直以为自己是一个比较喜欢专的人,这是不是偏离了一个大的方向冲进了一个小胡同,直到最近我才领悟,这其实是”软件工匠“的精神。但是这不代表不考虑全局,这只是一种情怀,一种态度,对于架构也是,对于代码也是,不要认为那些看似无关紧要的问题就忽视它,带着工匠精神雕刻它。

 

 

 

 

 

SOA与API的分裂和统一

虽然API和SOA有着相似的商业和技术目标,许多API的支持者却坚持表示API与SOA几乎没什么关联,认为它们属于截然不同的方法。他们经常宣扬务实的REST API和SOA之间有着巨大的差异。分工限制了SOA服务和RESTful API无法干净利索地集成到一个统一的架构中。

团队必须在SOA和API的观点之间建起一座桥梁,构建一个实际的规划去融合 API 和 SOA。

“做REST”和“创建API”的团队通常的关注点是,以增量的外部扩展、具体的演示和不涉及复杂技术的核心业务用例来克服技术和业务的障碍。而SOA团队通常关注的是,获得扩展效率、达到商业标准、建立决策中心和满足复杂的非功能性需求。

通过结合API和SOA的观点,当遵循商业策略和扩展需求时团队就能够迅速地交付业务解决方案了。

务实的REST API关注点

REST是一种系统开发的架构风格,它强制实行一系列服务交互的约束。正规的REST约束包括客户端-服务端和无状态的交互、可缓存的响应、不变的契约、分层的系统设计和按需编码。这些约束有利于特性的显现,也就是简单性、可扩展性、可变性、可靠性、可见性、性能和可移植性。满足REST约束的系统称为RESTful。RESTful设计方法能够增加许多的收益:

  • 使数据和服务更易于访问

  • 降低入门门槛

  • 尽最大可能扩展受众数量

  • 使API或服务被大量的用户代理消费

  • 使数据和服务逐步演进

  • 在运行期扩展系统

  • 对资源的修改不会影响到客户

  • 动态指导客户行为

  • 使系统可扩展、可靠和高性能

  • 简单

  • 可缓存

  • 原子性

虽然RESTful设计有益于支撑SOA的目标,但务实的REST的战略关注点与许多SOA的举措不同。务实的REST API设计团队专注于自下而上的应用场景、友好的协议或格式(比如HTTP、JSON、DNS)、宽容的接口定义和简单的交互模型(比如在保证送达之上的重试)。

务实的SOA关注点

务实的SOA专注于面向服务的模式,该模式着重于增加软件资产的价值。基本的面向服务的模式是:

  • 共享和重用资产

  • 将冗余的功能固定到稳定的部件中

  • 使项目遵守公共标准和最佳实践

应用这三种模式将减少IT环境的复杂度,带来更大的灵活性,比如,能够更加快速地构建应用、更加快速地修改以处理需求的变更。面向服务的模式推动开发团队去评估软件资产满足商业干系人需求的能力。

务实的SOA最佳实践

务实的SOA团队不强行推进公共(而且复杂)的标准。务实的SOA团队提供有价值的商业能力、降低应用的阻力并交付独特的服务价值。

务实的SOA团队不鼓吹难以操作的最佳实践。他们依靠团队间的传帮带和自动化的治理以简化最佳实践的应用,这使团队可以更轻松地做正确的事情。

务实的SOA团队会留意技能差异和应用的障碍。他们提供加速器包(比如架构、工具、框架和API或服务构建块)减少培训、增加自助服务的应用,以及加快项目的交付速度。

务实的SOA团队会平衡企业治理与项目的自主权。而不是竖立开发和注册门槛,成功的团队引入若干机制去改进服务、间接的交互、硬性服务水平并促进自助服务的应用,通过引入这些机制使团队促进服务的开发、服务的共享和服务的应用。你可以把这些机制当成现有API管理的核心。

务实的调和

REST与SOA是不同的,虽然它们并非格格不入。服务可以成为RESTful,RESTful资源也可以成为服务。像SOA一样,REST是由一组设计原则定义的架构规程,REST还强制施行一组架构约束。REST使用以资源为中心的模型,这与以对象为中心的模型截然相反(比如,通过资源来封装行为)。在REST中,你感兴趣的每件事物都是资源。当进行RESTful服务(也叫作API)的建模时,以一组资源来封装和暴露服务的能力。

因为SOA所呈现的架构目标状态通常与目前遗留的IT资产是有一定差异的,所以SOA是一个漫长的架构之旅,而不是一种短期实现。因为API使组织内外的业务能力相互连通,所以API能够为商业干系人提供一个平台,使他们可以在其上发起企业IT革新以及实行务实的业务。

什么时候去创建服务或者去创建API

当正要创建一个同时包含SOA和REST的统一架构策略时,下一个合乎逻辑的问题是:什么时候去创建服务或者去创建API呢?从消息传递的观点来看,服务和API有相似的属性。它们都是可访问的的网络终端,通过访问交付数据或触发事务。从架构的观点来看,服务和API都提供了分离关注点、创建松耦合解决方案的机会。许多架构师和开发人员都想要随着API一起扩展他们面向服务的架构(SOA),但并不清楚什么时候去创建服务或者去创建API。

什么时候创建服务?

作为一个可访问的网络终端,一项服务是一项已经发布的业务或者数据。当团队要网络域或运行期应用共享业务能力或业务数据时,创建服务。

服务应当实现一个适当自动化的业务任务,不应该设计成与其他组件交互的精细化组件。当服务暴露了业务流程中的一项独立任务时,开发人员和业务分析师更喜欢去获悉服务的目标。以业务任务的粒度去设计服务,减少服务的交互复杂度,简化应用的维护工作。举一些适合于面向服务的方法的业务任务的示例,它们包括“提交订单”、“检索客户记录”以及“缴费”。

接口与实现分离

服务封装了特定的实现,服务终端通常在服务与后端业务逻辑之间有一个一对一的关联关系。服务应该通过多种接口风格(比如面向资源的、发布/订阅的、方法调用的)暴露业务能力或数据。为了最大化有效性和范围,服务实现应该通过多种消息协议(比如HTTP、JMS、MQ)和消息格式(比如JSON、XML、CSV)去发布可访问的接口。

RESTful是一种接口风格。这种网络非常适用于移动应用、瘦JavaScript客户端应用以及跨网络和所有域的bash脚本访问函数。

理想情况下,接口风格不仅是详细的解决方案,还是重要的管理特性(比如安全性、服务层的强制实施、用法跟踪等),在所有接口风格(比如面向资源的、发布/订阅的、方法调用的)中这些特性都是有效的。图1展示了外观模式,连接了一个单一的服务实现和多个消费者:

图1:API外观模式

内在表征与外部契约和外部协议的分离,肯定会影响随着时间去演变服务实现的能力。当从已有的实现中清晰地分离出接口时,开发人员就可以修改其实现而不会影响到使用该服务的应用调用了。

然而,从共享的应用平台消除消费者和提供者的耦合,以及从实现中消除接口耦合都会增加额外的关注点。例如,如果试图使操作语义(比如身份、服务层、授权)跨不同的平台和分布式环境无缝地流转,那么难度就增大了。团队依靠中间件基础设施去桥接跨所有参与者和组件的语义。

因为从实现中分离接口引入了复杂度和额外的工作量,许多团队把接口紧紧地绑定在实现上。通过下述的架构最佳实践,并引入API外观或代理终端(使用自动化开发),团队可以增强解决方案的可维护性和适应性。

什么时候创建RESTful API?

RESTful API是一种与服务实现互补的接口风格。可在以下时机创建RESTful API,当要共享控制领域(比如业务单元、组织)之外的服务时,当以扩大影响范围和消费群体为目标时,当要提供跨本地web基础架构的服务时,或者对服务端、接口和实现的不对称演进极其感兴趣时。

如果开发团队发布已有服务前的API外观,他们要从服务的实现中分离出服务的接口。API端点是实施安全、监控使用和流量整形的轻量级代理。代理使消费者接口合约和后端服务的实现可以清晰地分离。

当应用服务器、企业服务总线节点或者数据服务主机可以发布API端点的时候,API网关是由API传送机制优先管理的。托管的API是:

  • 可主动发布和订阅

  • 与相关已经发布的服务级协议(SLA)一起有效

  • 安全的、已认证的、已授权的且受保护的

  • 通过分析可监控和可货币化

服务接口或RESTful API接口

RESTful API与服务是不一样的,虽然它们并非格格不入。服务可以成为RESTful,RESTful资源也可以成为服务。像SOA一样,REST是由一组设计原则定义的架构规程,REST还强制施行一组架构约束。

RESTful API接口是服务接口中一个有约束的子集。RESTful API暴露面向资源的接口,理想情况下符合HATEOS(超媒体作为应用程序状态引擎)。RESTful API发布资源为中心的模型,它与对象为中心的模型相反(比如,行为是以资源来包装的)。在REST中,感兴趣的每样“事物”都是一个资源。当对一个RESTful服务(也叫做API)建模时,服务的能力作为一组资源进行包装和暴露。

去创建一个RESTful API:

  1. 为所有事物指定“ID”

  2. 将所有事物链接在一起

  3. 使用标准HTTP方法

  4. 允许多种消息格式的表述

  5. 减少共享的状态

新兴的API设计工具将帮助你把一个服务实现转换成一个RESTful API。

 

 

 

 

SOA落地少不了BPM

SOA落地少不了BPM


事实上,近年来随着越来越多的企业及政府单位对信息化建设有了更加深入的理解,信息化已经开始从最初的建设阶段走向了广泛应用阶段。曾经企业为了实现某种特定的应用而构建的一个个独立系统,现在已经制约了系统间的数据共享,也阻碍着系统效率的提高。如何消除这些信息孤岛,使各类信息资源实现彼此间的关联、整合、协同和互动,正在一次次地考验着企业信息系统的建设,而这正为那些基于SOA中间件或平台厂商的发展带来了巨大空间。而区别于SOA所推崇的以技术创新驱动实现业务需求的做法,国内的大部分BPM中间件及平台厂商则更多的是以业务为核心,以业务领域的需求为出发点,结合实际对BPM应用或平台进行开发。在开发的过程中,厂商力求通过逐步增强系统的集成能力并实现较为丰富连通性,最终达到缩短业务交付周期同时增强综合竞争力的目的。使系统更加地基于组件化、服务化, 并且朝着SOA的方向前行, 最终实现SOA与BPM的完美融合。可以说,在SOA落地后,BPM可能会起到更大的作用。


业界人士表示,“在SOA战略部署BPM来改进业务流程的威力在于它有可能让一直处于追随地位的企业成为行业领导着,并且保证它们持续的成功。不过,要达到这个目的,必须保证业务流程与具体的信息技术和应用无关,保证集成技术与实现流程的应用和资源无关,否则,流程逻辑很可能是基于某一个专门的技平台硬编码而成,如果是这样的话,将来需要修改的时候就会非常昂贵,从而导致整个BPM的最终目的落空。”因此,在业务流程在SOA架构中实现之前,需要对它们进行建模,这一点现在越来越重要,特别是对BPM需要越来越强烈的今天。但这里首先需要理解BPM不仅是一门管理的学科,还是一个技术平台,而且在一个比较大型的BPM项目中,建模一个辅助但非常关键的步骤。


作为一门管理的学科,BPM一改过去认为经营活动就是一些分散的业务组织、各种系统和指标的观点,BPM认为,经营活动是一些与高层经营目标密切联系的超越具体功能的流程。作为一种技术平台,BPM提供了一组软件工具用来进行性能优化,让那些抽象的性能指标具体化,把它们与流程数据联系起来,实现流程的自动化和流程活动的监控,并提供一个可以灵活地进行性能改进的平台。BPM最迷人的地方在于,BPM能通过利用或重用企业现有的技术投资给企业提供更高的灵活性。一旦企业认识到这一点,企业就能更好地理解建模是如何帮助管理,以及BPM通过SOA实现企业更好的经营。


让企业充分认识BPM在SOA中的作用是非常重要的。BPM对于SOA的重要程度正如在SOA中部署业务流程之前需要对业务流程建模一样,因为BPM能让企业从以前通过硬编码实现流程的自动化中解脱出来,从而给企业更大的灵活性,而这种灵活性正是现代企业所必须的。BPM的另一个好处是,不用硬编码以后,企业能实现业务流程的持续改进,而且能非常容易地在整个企业内部共享。


其实,随着企业开始注意到SOA给企业经营带来好处, 它们也正在意识到建模是SOA成功的最重要的步骤之一。这主要是基于这样的事实,即建模帮助企业在流程实现之前将内部的流程与企业的战略和目标结合起来。更具体来说,建模有助于企业可视化地理解和记录业务流程,这对于缩小目前在企业的业务部门与IT部门之间对业务理解的差异非常有帮助。因为业务流程是定义好的一组为了完成某一任务的活动,而建模能在流程部署之前确保最佳实践能被纪录下来,并在整个企业内部进行交流。“例如,业务分析师能通过建模定义不同的场景,分别对应不同的资源位置、在整个决策过程的不同决策点时的假设和其他的参数,来看看哪一个情形成本最低、平均周转时间最快、最不可能违背服务级别协议或者符合其他的约束条件。此外,这种模拟还有助于在真正部署前对新的流程进行分析,揭示流程中的瓶颈,从而节省时间和成本。”

 

 
 

SOA 和 BPM 之间如何协同工作

SOABPM如何很好的共同工作?实际上它们是两个完全不同的原则。SOABPM在结构上是相同的。举个例子,它们就像是“流程同构”。同构指的是一个保持结构的双射。在更一般的范畴论语言中,同构指的是一个态射,且存在另一个态射,使得两者的复合是一个恒等态射。

面向服务的体系结构(Service-OrientedArchitectureSOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种这样的系统中的服务可以一种统一和通用的方式进行交互。

业务流程管理(Business ProcessManagementBPM)是一套达成企业各种业务环节整合的全面管理模式。BPM涵盖了人员、设备、桌面应用系统、企业级 Backoffice 应用等内容的优化组合,从而实现跨应用、跨部门、跨合作伙伴与客户的企业运作。BPM通常以Internet方式实现信息传递、数据同步、业务监控和企业业务流程的持续升级优化。显而易见,BPM不但涵盖了传统“工作流”的流程传递、流程监控的范畴,而且突破了传统“工作流”技术的瓶颈。BPM的推出,是工作流技术和企业管理理念的一次划时代飞跃。

SOA环境中,流程同构意味着,假设:“如果你要模型化业务流程,作为单独的操作,模型化服务构成的实施的这个流程,这两个模型有同样的结构,也就他们是同构的。”

以这样的方式看待SOA-BPM,协助确立业务和IT之间的通用语言。

业务人员可以探讨流程,IT人员可以探讨SOA,而且在某种程度上,他们在探讨同样的事情。如果流程专家希望把业务服务作为流程子任务思考,他们可以继续这样进行。同样的,如果技术实施人员更喜欢把业务流程作为服务组件思考,这样也可以。最好的就是,当BPM团队在白板上描绘流程加工标准,SOA团队在另一个白板上描绘具体构成,两个图标看起来实际上很像。如果这不是业务和IT的对齐,又是什么呢?感性的SOABPM之间的“裂缝”,这个裂缝更多地是语义方面的产品,而不是实际上的两个原则的结构上的不同。SOA提供服务集合,可以按需映射业务流程。

 

 

 

SOA | 基于服务总线的设计

SOA的概念犹如今日“云计算、大数据”一样,被炒得火热,不少企业便纷纷响应,并宣称会拥抱和实施SOA。而事实上,业界出现了两种极端:一种是由于各类文章和书籍关于SOA的描述往往太过抽象,再加上各大厂商的呼吁,使得SOA往往显得“高大上”,令不少企业和架构师们望而却步。第二种恰好相反,有部分人却认为SOA无非是“新瓶装旧酒”。

 

个人理解,SOA在宏观上确实太复杂,因为它涉及到的不仅仅是技术和架构本身。而从技术的视角来看,并非难以落地。

 

SOA全称“面向服务架构”,它提供的是一种架构风格和理念,而并非是一种技术或者产品。并不是说项目中用了WebService、WCF、Hessian、RMI之类的就是SOA了。

通俗点来讲,SOA提倡将不同应用程序的业务功能封装成“服务”并宿主起来,通常以接口和契约的形式暴露并提供给外界应用访问(通过交换消息),达到不同系统可重用的目的。

流行的WebService等可以看作是实现SOA基础设施的技术方法。当然,实践SOA不仅需要解决服务调用的问题,还包括服务编排、服务治理、服务路由、服务监控等一系列的问题。在大型分布式系统中,SOA被广泛实践,但是在不同的应用场景中,设计方法也大不相同。

 

SOA是一个组件模型,它能将不同的服务通过定义良好的接口和契约联系起来。服务是SOA的基石,在开始服务设计和SOA实践之前,有必要先了解服务的概念以及服务的常见特性。

 

 


何为服务

服务的概念非常宽泛,在宏观上,服务的理解是“为他人做事,满足他人需要,而且通常是不以实物形式提供劳动的…”。在SOA系统中,服务指的是应用程序的功能单元,它通常体现了业务功能。服务是一种抽象,它向服务使用者隐藏了服务内部的实现细节。根据服务设计的基本原则,服务可能会具有以下特性:

  • 自治(理)性

    服务应该是独立部署和运行存在的,且边界清晰,应尽量减少对外部的引用和依赖。

  • 粗粒度

    服务调用是需要开销的,这也是实现松耦合的分布式系统必须付出的代价。因此,应尽量通过一次服务调用传输所有需要的数据,而不是分多次去调用服务和组装数据。

  • 可见性

    服务是对外提供的,必须在某公共的地方可搜寻和发现,且服务要有必要的描述。

  • 无状态

    服务不应该依赖于其他服务的上下文、会话等,尽量减少不必要的状态管理流程所带来的资源消耗。但是,对于业务流程服务而言,状态数据是不可避免的。

  • 幂等性

    当消费者调用服务后,服务调用可能会有“成功、失败、超时”这三种状态,当服务并没有最终响应完成时,消费者可以尝试反复地调用服务,这样仍不会影响到最终结果。

  • 可重用性

    服务应该是可以被重用的,相同功能应可以调用相同的服务,这也是软件设计的原则。

  • 可组合

    服务是可以被当作成一个步骤的,服务也可以调用其它的服务。这样能够灵活的组合。

 

有关服务的“粗粒度、无状态、幂等性”等特性,一直是饱受争议的话题,可谓见仁见智。这里有必要说明下,这些特性并不是服务不可或缺的,应当在实践中根据需求来取舍。


SOA所面临的问题

SOA架构将公共的业务拆分出来,形成可共用的服务,最大程度的保障了代码和逻辑的复用,避免了系统的重复建设,并且让应用程序的部署找到了一种持续可扩展的方案,给应用抗负载能力带来了质的飞跃。

SOA架构所面临的一大问题就是如何解决集成服务应用普遍存在的一致性问题,举例来说,同时调用多个服务,当其中一个服务调用失败时,其他服务已经处理执行的结果该如何进行回滚,这在单机本地调用的情况下使用事务比较好处理,而分布式环境下的事务将问题复杂化,并且性能开销难以承受,因此,只有在极端情况下才会考虑强一致性,一般情况下更多的关注最终一致性。另外一个就是安全问题,面向企业的平台级的SOA架构,需要对参数传递、响应内容以及各种用户私有信息的交互,有着更严格的且特殊的安全需求,如何构建一个安全的SOA架构体系,也给技术人员带来了很大的挑战。


在讲了很多“大而空”的理论之后,估计很多人要拍砖了。下面将会讲一些干货,更贴合实际应用。

基于服务总线的设计

基于总线的设计,借鉴了计算机内部硬件组成的设计思想(通过总线传输数据)。在分布式系统中,不同子系统之间需要实现相互通信和远程调用,比较直接的方式就是“点对点”的通信方式,但是这样会暴露出一些很明显的问题:系统之间紧密耦合、配置和引用混乱、服务调用关系错综复杂、难以统一管理、异构系统之间存在不兼容等。而基于总线的设计,正是为了解决上述问题。总线则作为中枢系统,提供统一的服务入口,并实现了服务统一管理、服务路由、协议转换、数据格式转换等功能。这样能够将不同系统有效地连接起来,并大大降低了连接数(每个子系统只需要和总线建立连接)和系统间连接拓扑的复杂度。如图所示:

 

基于服务总线的设计,往往需要ESB(Enterprise Service Bus,企业服务总线)产品来充当基础设施。ESB采用了“总线”这样一种模式来管理和简化应用之间的集成拓扑结构,以广为接受的开放标准为基础来支持应用之间在消息、事件和服务的级别上动态的互连互通。 ESB是一种在松散耦合的服务和应用之间标准的集成方式。

在其内部设计和实现中,通常会应用到一些经典的架构模式,例如:Broker模式、消息总线模式、管道过滤器模式、发布订阅模式等。这里,我们将重点介绍这几种核心的架构模式。


Broker模式

Broker可以看作是服务总线中的一部分,通常应用于同步调用的场景(调用服务后阻塞,等待远程服务响应完成后再返回结果)。Broker可以看作是代理、分发,意味着对服务的调用,可以直接通过Broker来完成。在软件架构设计中,向已经存在(引用或者调用)关系的两者中间加入“第三者”是一种常见的解耦方式,显然,Broker也不例外。如下图所示:

 

为了进一步加深读者对Broker模式的理解,这里通过举例来说明:

在现实生活中,我们需要租房子(可以看作是一种服务调用),可以通过几种途径来完成。第一,我们可以先在网上了解,然后跑到目标小区去询问和看房,最后再找房东签合同等;第二,也可以直接找附近的地产中介,说出我们的要求和预算,请中介直接帮我们搞定一切。很明显,第一种方式,需要自己对目标有足够的了解而且还要亲自去找房东签合同(依赖具体,可以看作是紧密耦合),而第二种方式,仅仅需要告知中介需要什么即可完成租房,甚至都不需要知道哪个小区有房子、房东到底是谁等这些信息(依赖抽象,并通过第三者来实现解耦)。当然,找中介虽然省事,也会产生额外的经济开销。同理,通过Broker来调用服务也可能会产生一定的开销。

 


消息总线模式

SOA系统有三种基础组件:消息总线、信息转换/处理引擎和存储库。一般来说,这些组件会集成到ESB中,而在这些基础组件中,消息总线是最重要的。消息总线主要应用于异步通信场景(投递消息后立刻返回结果,而不用等待远程系统返回执行成功),可以大大提升响应速度和系统吞吐量。当然,消息总线也同时支持同步通信模式。基于消息总线模式的设计中,消息中间件屏蔽了系统间底层通信的细节,是比较典型的(异步)松耦合的架构。

在企业中,随着业务的逐渐发展,各大系统之间的调用交互变得非常频繁,关系错综复杂。

想象如果有几十或者上百个系统(在保险、金融领域很常见),将变得难以维护。通过引入消息中间件,便能有效的解决这些问题。不同系统之间,只需要连接到消息总线,能保证成功投递/接收消息即可。对于消息投递者(生产者)而言,根本不用关心消息的接收者(消费者)到底有哪些,也不用关心消费者接收到消息之后该如何处理。对于接收者(消费者)而言,只需要关注与自己有关的消息,接收到消息后并做出相应的处理即可。如下图所示:

 

比较典型的应用场景:张三在CRM系统中录入了一条客户签约订单的信息并审核通过后,CRM系统会向消息总线投递一条消息(消息中包含必要信息,例如员工ID,订单编号,产品编号和交易金额等,而CRM系统不用关心有哪些系统会接受到该消息)。员工绩效奖金管理系统订阅了该消息主题,收到消息通知后开始处理(给张三执行加奖金操作),同时,进销存系统收到消息通知后也会即时地更新商品库存的数量。这样,便实现异构系统之间的松耦合、异步通信。当然,真实场景可能比这里更复杂,但是实现思路上都大同小异。

 

在理解了上述实例之后,有必要了解下Java EE中被广泛应用和实现的JMS(Java消息服务)。

JMS是一种关于消息的规范,业界流行的ActiveMQ则是实现了JMS规范的开源消息总线。

JMS支持两种模式:发布/订阅模式和队列模式(点对点模式)。其中,发布/订阅模式借鉴了现实生活中的出版社(发布图书)和读者(订阅图书),消息的消费者(读者)只需要订阅自己感兴趣的消息(图书)即可,消息生产者(出版社)生产(出版)了消费者(读者)感兴趣的新消息(新书)后,会通知消费者(读者)接受处理。在JMS发布/订阅模式中,通常以Topic(主题)来标识消息,是一对多的模式,意味着同一个主题可以同时被多个消费者来订阅和消费。而在JMS 队列模型中,通常以Queue name来标识消息,是一对一的模型,意味着同一条消息只能被一个消费者接收并消费(且只能被消费一次)。在生产者和消费者都是集群的环境中,通常需要将这两种模式结合起来使用,情况会复杂很多,而且需要考虑容错性、负载均衡、消息一致性、消息优先级等复杂的问题。

业界主流的消息总线(消息中间件)产品,普遍支持消息过滤、自动重试、分布式事务、持久化、消息优先级、消息回溯、(生产者/消费者/中间件自身)集群、故障转移等高级特性。

 

 


总结

 

基于总线架构的主要优势在于:

  • 可扩展性

    使用消息架构,可以在不影响现有应用的情况下增加或移除应用。

  • 低复杂度

    每个应用只需要和总线通信,只有1个连接点,降低了应用程序集成的复杂度。

  • 灵活性

    对于构成复杂处理的应用程序通信组来说,只需要改变配置和控制路由参数就能满足业务逻辑或者需求变更,而不需要更改服务本身。

  • 松耦合

    应用程序直接和消息总线通信,不依赖其它应用程序,因此可以替换和修改。

  • 可扩展性

    可以把多个应用程序附加到总线上,进行并发处理,达到负载均衡的目的。

 

基于总线的模型,可以面向同构和异构系统(跨平台)。当前主要应用于传统企业应用的整合与系统集成中(例如:电信、保险、金融等行业)。由于基于总线的模型是一种集中式的架构,总线自身容易形成性能瓶颈,而且在实现高可用和容错性方面的复杂度和成本相对较高。所以,该模式并不是很适合于高并发、高性能、高吞吐量的互联网应用。

 


注:关于消息总线(消息中间件)的知识点很多,在实际应用中还有很多更加深入和复杂的细节问题。由于篇幅问题,笔者就不做过多的细节介绍和展开,感兴趣的读者,可以自行去查阅相关资料或者参考开源产品,做深入的学习和研究。

ESB产品主要包括:开源Mule ESB、ServiceMix、JBoss ESB,商业的Oracle ESB、BEA AquaLogic ServiceBus,.NET领域的NService Bus、MassTransit、东方通TongESB等。

MQ产品主要包括:ActiveMQ、RabbiteMQ、ZeroMQ、RocketMQ、Kafka、MSMQ、IBM MQ、东方通TongLINK/Q等。

 

 

 

 

SOA架构设计经验分享—架构、职责、数据一致性

背景介绍

 

 

最近一段时间都在做系统分析和设计工作,面对的业务是典型的重量级企业应用方向。突然发现很多以往觉得很简单的问题变得没有想象的那么容易,最大的问题就是职责如何分配。论系统架构设计的最大的问题,其实也就是职责的分配,分配的合理,实现起来就会很柔性,反之就会使架构很混乱。

 

软件的生命周期大概可以归纳为四个基本的过程,分析、设计、实现、测试,当然这仅仅是一个最为粗略的表示而已。不同的方法论有着不同的使用这几个过程的方式。RUP使用快速迭代的过程,在这个几个子过程中适当的输出一些过程制品,每次迭代都是进行相同的分析、设计、实现、测试。而在Scrum中,不提倡输出任何文档形式的过程制品,也同样有着上述几个过程,强调以人为中心,通过沟通来解决大部分的问题。

 

不能用好与不好来判断哪一种方法论,只能根据目前的实际情况综合权衡。RUP的每次迭代中有几个关键的制品对系统分析、设计很重要,可以说是非常重要,如:词汇表、业务规则文档、用例、领域草图。这几个制品对分析、设计很重要,需要从这几个制品中提炼出设计模型最终才能落地。这主要用在业务复杂的应用系统中。而Scrum更加的轻量级,可以用在互联网项目中,业务不是太复杂的情况下。

 

其实我为什么要强调软件工程及开发方法论,是因为我最近发现,做设计其实是建立在分析的基础上的,但是这里面又有很多问题。大型企业级应用,并不能通过一次性分析就可以得出准确和全部的需求,初期阶段建立的需求70%都是不准确的。所以做架构需要有分析的能力才行且是建立在适当的开发方论上的分析,什么时候该用RUP,什么时候该用Scrum,什么时候该用XP都很有讲究。分析与设计都需要有一个执行上下文,不同的上下文对分析、设计的执行有着不同的要求。

 

有句话我觉得对架构者来说很有启发:分析就是做正确的事,设计就是正确的做事。架构跟语言跟平台关系不大,毕竟架构是设计过程中的子过程,我想如果你的设计不合理,你用任何语言任何平台都解决不了问题。(这里的架构上下文指:企业应用架构不是基础设施的系统架构)

 

SOA的架构层次

 

进行SOA类型的架构设计就需要搞清楚SOA架构模型才行。并不能想当然的对系统进行简单的拆分就行,需要搞清楚SOA的架构模型是怎样的,每一块是干什么用的,这样设计由分析阶段输出的需求时才能正确的划分职责。

 

如果把SOA的架构简单的理解为是多个子系统之间的整合其实有点太过于简单,也没有真正搞清楚SOA的架构模型。按照SOA的正确方法论及目标模型,其实SOA在实现架构落地上,需要考虑到对服务的组合,不断的重用现有的服务,让企业应用可以逐步集成,快速实现业务的迭代。其实这就是本节要讲的服务的分层,通过分层将服务按照使用类型进行分配,上层服务对下层服务的包装,下层服务负责原子性的操作,上层服务对下层服务进行业务性的组合。

 

我们来看具体的每一层的作用及主要职责。

 

 

 

1
应用服务(原子服务)

 

 

应用服务就是诸如:订单服务、仓库服务、销售服务、客户管理服务,这些服务直接对应不同的应用系统,直接服务这些应用系统的原子操作。订单服务直接原子性的插入订单,没有任何跨其他服务的分支逻辑。仓库服务只管自己的仓库逻辑。同样其他的应用服务只管好自己的职责,杜绝对其他服务的调用。

 

图1:

应用服务位于UI与后台之间,后台我们可以认为它是一异构的系统或者是数据库之类的。应用服务的位置位于前端与后端之间,起到类似一个服务API的作用,但是SOA中的服务还远远不止这一个应用服务,如果我们的SOA架构中只有一种类型的服务,那么这会增加我们系统的耦合程度,因为你没有对系统的服务进行层次的划分,你的业务功能会直接的落到某一个应用线上的服务,继续往下看。

 

 

 

2
组合服务

 

 

 

组合服务是对应用服务的一个组合,根据实际项目的规模大小,不一定非要进行物理的隔离,在代码层面的服务化也是可以的,在将来的某一天有必要的情况下再进行物理的拆分,毕竟物理的拆分有着严重的成本和代价,对系统的稳定性带来很多挑战。所以经验告诉我们必要的时候在进行拆分。”分布式系统设计的第一个原则就是尽量不要分布式“,这是马丁.福勒大师说的,现在理解确实感同身受。

 

图2:

组合服务对下层的应用服务进行了组合,完成了一个基本的业务动作,应用服务中是最基本的基础性的原子性的操作。但是在复杂的业务需求下大部分业务功能都需要跨越多个应用线来完成一个最外层的企业动作。提交订单可能需要穿过很多应用线,订单管理、仓库、财务等等环节。所以这里我们还需要一个能在最外层对组合服务进行编排的业务服务。这个编排服务可以完全是自动化的,通过工作流引擎进行组合自动化来完成,这对企业应用的自动化流程很有意义。

 

 

 

3
业务服务(编排服务)

 

 

 

业务服务是最外层的服务,向下编排了组合服务。业务服务位于最上层,当需要有跨越多个应用线来完成的业务,这个业务就放入业务服务中。比如提交订单,先检查库存、扣减库存(冻结库存),然后下单,再往后通知财务,再往后通知物流等等都是一个复杂的企业服务线。这种最外层的业务逻辑如果你不进行SOA分层然后将其放入最外层的业务服务中,你把它放入任何一个应用线都会使系统调用混乱不堪。所以问题就是需要进行纵向的划分层次。如果进行了SOA的层次划分后就不会出现互相乱用的情况。其实这里可以参考阿里的服务设计方法。(李智慧写的一本大型互联网架构与实践里面也讲到了服务要划分层次)

 

图3:

当在业务服务中执行的业务逻辑时,需要跨越多个应用线来完成。这部分的逻辑也说是职责,如果不放入这个位置,放在哪个应用线都不合适,放入哪个应用线都会使系统调用出现混乱。其实这里的问题就是我们不能用一个维度来进行SOA系统的设计,本来服务就具有组合特性,所以适当的提升服务的层次是有好处的,但是应用服务和组合服务可以在代码层面上进行构建,而业务服务也叫编排服务是需要进行物理隔离的,毕竟考虑到系统复杂度和稳定性问题这是值得的。在排查问题,系统性能、稳定性等等方面,物理的隔离有一定的作用,毕竟业务服务本来就是来组合多个应用线的,这样做会使整个系统架构很清晰。

 

SOA化的重构

 

进行SOA化的实施,大部分情况下都是对现有系统进行重构后考虑的,初期企业发展阶段以快速出原形为首要目标,只有当系统出现瓶颈了才会考虑运用SOA来解决。但是在这个时候有很多历史包袱无法解决,进行SOA化的重构其实成本是很高的,而且很危险,对有些复杂的逻辑说的现实点,是无能为力的。如果都可以通过重构这个技术来解决,那我们就太天真了。《重构—马丁.福勒》一书讲的是代码层面的重构,跟做系统级重构两个概念。对系统级别的重构还没有太多成熟的方法论支撑。尤其现在新技术层出不穷的,各有优点,能很好的运用这些技术、方法论、过程来重构大型企业级系统,难度非常大,这需要整个公司投入很多人力、资源成本。回过头来想想,其实在前期适当考虑一下还是有必要的,这样可以减少后期很多技术债务。

 

这里我只总结我在分析、设计公司某一块业务系统的时候对其进行SOA化的重构思路。重构本来就是一个不断迭代的过程,不可以跨大步。通过很多脚手架支撑,让系统慢慢的过度到新的SOA架构下,既然要实施SOA架构,那么很重要的一点就是对迁移的业务逻辑适当的归类,什么业务逻辑该放入“业务服务”中,什么逻辑该在代码层面上放入“组合服务”中,对基本的操作有如何放入代码层面的“应用服务”中。

 

保留服务空间,为了将来服务的组合

 

在进行系统拆分的时候,对当前后端的调用都进行适当的规划,将其分为两类,一类是应用服务,一类是组合服务,这两个服务是可以在代码层面上进行抽象。重点是那些调用其他系统的地方,需要将其放入业务服务中,这块逻辑比较复杂,难以抽取,需要适当的结合”数据落地“的思路来综合考虑。有时候把一部分数据落入本地可以提升系统的整体简洁度和稳定性,但是要考虑数据的一个生命周期性质。

 

在迁移的过程中可能还会有一些新的功能并行开发的,既有新的逻辑需要放入新的SOA服务中,也会有迁移过来的逻辑,这两个过程同时进行其实很痛苦,尽量避免这样同时进行,但是现实是根本不可能,正常都是一起并行推进。如果这两个过程是同一组团队负责其实还好,毕竟对这块的代码、业务都比较了解。

 

这一节目的是想强调对现在系统进行迁移的时候要考虑服务的层次,不要只进行一个简单的搬移代码,这个时候是一个对代码进行重构的好机会,该划分层次的要划分层次,该读写分离的要读写分离,要重点考虑那些“业务服务”,需要跨越多个应用线的逻辑。

 

顺便说一下,还有一个重点就是迁移的时候还要考虑数据存储方面的迁移,光代码层面的迁移只是第一步,第二步还需要进行数据层面的迁移。当然这两个大的步骤都是要通过很多次迭代完成,并且还是一个对业务、代码进行很好梳理和整理的好机会。

 

运用DDD+GRASP进行分析和设计(防止主观的判断导致错误的假设)

 

做系统设计时最怕的就是职责搞错了,这会使系统的架构突然就复杂了,而且系统架构都是很难改变的或者压根就无法改变的决定。所以我对这块引起了重视,有时候你对业务在了解在熟悉依然会搞错职责,对于这块光凭主观的判断是不长远的,无发复制、无法传播的,也无法落字成文的。

 

对DDD我这里就不多做介绍了,这里要强调是GRASP。运用DDD可以很好的帮助我们来战略性的观察企业所坐立的领域,我还是很提倡DDD在公司实施的,不说DDD中的“战术设计”方法论,就光说它的“战略设计”方法论还是有很大作用的,让我们可以在脑海中建立一个战略性的模型。具体要不要进行代码层面的落地这就看实际情况了。而且DDD中的很多不错的思想都可以借鉴过来,包括领域通用语言,有了领域通用语言团队之间的沟通和交流会节省很多成本。对于新人来说,可以很快的了解公司的一些大概的业务,这和“词汇表”其实还是有区别的。

 

上面说了,在划分职责的时候很多都是通过经验来主观的判断,没有其他的客观证据了。那么有没有一个不错的方法论或模式来指导我们进行这类问题的解决呢,其实还是有的,因为在国外人家这方面已经很成熟。

 

GRASP就是这样的一套模式,它可以帮助我们进行客观的设计职责。到底该把这块数据放入哪个应用中,到底该把这个逻辑放入哪个服务中,都有指导,包括对对象层面的设计依然可以。我们可能对“信息专家模式”都有了解,但是以往我们可能都只把它用在对象设计上,而没有提升一个系统层面中考虑。那是因为我们以往可能没有碰见很复杂的职责分配场景,只有当出现问题时我们才能真正领会某个东西的好坏。

 

DDD只有结合GRASP才能客观准确的方配某个领域的职责,不管是战略设计层面还是战术设计层面,都是一个很好的平衡标准,不会由于技术人员主观的兴趣倾向导致一个错误的职责分配决定,而这个错误的决定最终是要开发人员来买单。

 

SOA分布式下的数据一致性

 

传统分布式系统与当代的面向SOA的分布式系统有一定区别,论概念上来讲SOA是以服务为中心,既然以服务为中心就会有很多面向服务的设计原则。而传统的分布式系统没有服务的概念,也没有所谓的一切皆是服务的原则。而当代SOA则首要原则就要以服务为中心,针对服务的设计又有了很多服务设计原则。

 

SOA对服务还进行了类型的划分,按照服务的应用层次来分类:业务服务、组合服务、应用服务,包装服务等。再按照管理与运维的层面来分类:控制服务、调度服务、监控服务等等。传统的分布式系统是没有这些的,我们谈论的是当代SOA的分布式系统,所以我们强调的是以服务为中心,以服务设计原则为架构设计的指导要求,当代SOA是对传统分布式系统的一个迭代进化,不是一个时代的产物,SOA更加强调了以服务为首要原则,已经提升到了另外一个更加高级的层面。

 

本节我们交流一下在当代SOA分布式系统中的数据一致性问题,在SOA中这主要涉及两个层面来考虑,一个是服务层面、一个数据持久化层面。再按照一致性的基本要求,可以分为:读一致性、写一致性、会话一致性、最终一致性、实时一致性等几个维度,当然还有其他几个维度的一致性要求。

 

我们这里重点讨论在企业应用中实施SOA时遇到的一些比较棘手的数据一致性问题和解决方案,对于刚才提到的几个维度的一致性要求均具有重要的参考价值。

 

 

 

1
分布式事务

 

 

 

以往包括目前很多项目还是倾向于使用DTC来处理分布式事务,这个方案多数适用于一般的企业应用,业务、访问量、数据量要求都不是很高的情况下。用DTC很方便,事务的自动传播、事务的自动感知、事务的自动回滚和提交,这都是中央DTC帮我们管理好了。

 

由于有中央DTC的统一协调,看似好像帮我们解决了很多我们需要考虑的问题,但是它也是整个平台的致命的瓶颈,一旦DTC由于某个问题出现错误,而且这种错误都是系统层面的错误,很多问题我们是无能为力的。如果出现问题,整个应用平台都无法完成任何一个跨服务的业务流程,这其实很危险,你不无法控制系统的稳定性。

 

这里总结,DTC用于一般的小型企业应用,不建议用在中等规模的企业应用中,不是说这个东西不好,而是无法控制它。

 

 

 

2
事务补偿

 

 

 

世界级SOA专家所编写的书籍里都提到了使用“补偿”操作来完成数据的不一致性,当我们编写了一个服务方法A,就需要一个服务方法A1的补偿接口来完成A服务的补偿操作。但是真实的业务情况下很难实施这种看起来好像很优美很柔性的设计。没有实践就没有发言权,我们公司的技术团队就实施过这种方案,但是很不理想,这跟技术本身及技术团队没关系,只是我们的平台业务太复杂,很难去“补偿”一个已经做过的操作。

 

这当然也要看你所面对的项目情况,量变引起质变,如果你的各种量都上去了,这个“补偿”方案不实际,而且很难在数据层面进行“补偿“。总之,这不是一个中长期的方案。

 

 

 

3
异步EDA

 

 

 

EDA简称”事件驱动架构“。多个系统之间通过传播”事件“来驱动整个业务的运转。系统之间没有紧耦合的同步调用的操作,都是通过发出异步的“事件”来通知下一个业务环节。

 

可能你会有一个疑问,异步操作,是不是系统之间延迟会很长,其实不是,现在有很多成熟的消息中间件在内网内几乎是毫秒级别的延迟,至于跨机房就看物理上的距离了。

 

异步操作有很多好处,这里我就不浪费大家时间重复那些好处。使用EDA实现系统之间的一个松散的事务关系,要把控好项目的质量,对系统的非功能需求、BUG数等等可能会影响业务操作中断的地方都要建立起适当的机制,让这些问题尽早的在线下解决。比如可以实施UnitTest、持续集成等一些敏捷的方法论。

 

总结

 

同样一个工具在于什么人用,真正的工匠都是使用很朴实的工具来雕刻无法超越的艺术品,这就是工匠情怀。最近对工匠情怀感受越来越深,一直以为自己是一个比较喜欢专的人,这是不是偏离了一个大的方向冲进了一个小胡同,直到最近我才领悟,这其实是”软件工匠“的精神。但是这不代表不考虑全局,这只是一种情怀,一种态度,对于架构也是,对于代码也是,不要认为那些看似无关紧要的问题就忽视它,带着工匠精神雕刻它。

 

 

 

 

 

正确理解SOA、SaaS和云计算的关系

  随着云计算的概念受到越来越多的人的推崇和论证,“云上的日子”看起来离我们越来越近了。几乎所有的IT厂商都不约而同了启动了各自的云计算战略。但是由于每个企业的战略出发点不同,企业推出的云计算概念也有所差别。如果仅仅以自己的产品和业务为标准,片面地将云计算理解为SOA或SaaS,则不仅混淆了云计算概念,模糊了其产品形式, 还阻碍了云计算的推广和应用。那么, SOA、 SaaS等同于云计算么?它们有什么区别?我们应当如何正确理解这三者之间的关系呢?

 

解惑云计算、SOA与SaaS

 

  云计算涵盖的范围很广泛,内容也很丰富。我们通常可以把云分为三个层次:硬件层的基础架构云(Infrastructure as a Service, IaaS)、平台云(Platform as a Service, PaaS)和软件应用云(Software as a Service, SaaS)。目前大家对于云计算概念的理解,主要有两个误区:一是片面地把SaaS视为云计算;二是以为运用了SOA架构就感觉好像实现了云计算,于是就把SOA和云计算等同起来。

 

  实际上,SOA作为一种面向服务的架构,是一种软件架构设计的模型和方法论。从业务角度来看,一切以最大化“服务”的价值为出发点,SOA利用企业现有的各种软件体系,重新整合并构建起一套新的软件架构。这套软件架构能够随着业务的变化,随时灵活地结合现有服务,组成新软件,共同服务于整个企业的业务体系。简单的理解,我们可以把SOA看作是模块化的组件,每个模块都可以实现独立功能,而不同模块之间的结合则可以提供不同的服务,模块之间的接口遵循统一标准,可以实现低成本的重构和重组。在SOA的技术框架下,可以把杂乱无章的庞大系统整合成一个全面有序的系统,从而增加企业在业务发展过程中应用系统的灵活性,实现最大的IT资产利用率。

 

  SOA技术其实在几年前就已经出现了,但是任何一种IT技术,真正要产生效应,都必须要以大大降低实际系统的使用、维护以及升级的成本为前提。更重要的是,一种技术的普及需要,都只有在这种技术不断成熟,并且形成相应的规模应用之后才能实现。

 

  SaaS则是一种基于互联网技术的软件价值交付的新型业务模式。具体地讲,SaaS是按照使用者的需求提供软件应用服务的业务模式。SOA架构可发挥其在系统界面和接口标准化等方面的优势,为SaaS提供一个较好的技术平台,从服务管理和系统运维角度为SaaS提供有力的技术支撑,从而有助于灵活地构建起一个用户成本最低的SaaS方案。

 

  由此看来,SOA与SaaS有着必然的联系:两者都面向服务。但两者也有着明显的区别:SaaS侧重于运营和交付,SOA侧重于平台架构。所以,SaaS是云计算的最终价值交付运营模式,SOA是实现云计算开放架构的基础理念之一,两者都包含了云计算的某些重要特征,但是他们都不能称之为云计算的全部。

 

互联网技术催生云计算、SaaS与SOA的汇合

 

  云计算与SaaS、SOA三者本身的发展轨迹和侧重点不同,但是却又互相联系,互相影响。

 我们可以从云计算的发展历史来看,云计算的模式就好比以前在大学或者政府的研究机构里面的大型计算机中心。计算机中心把计算机的计算和存储资源以租用时段的方式提供给内部各个科研单位,或者提供给外部用户。从过去的大型计算机时代到个人计算机、企业服务器的兴起,计算、存储资源开始分散于企业。但是如今,企业面对成千上百台服务器以及上千种不同的软件,运维成本越来越高。云计算可以把所有的计算资源虚拟化,进行动态管理,进而大大降低企业的IT运维成本,因此已是一个颇有影响的技术趋势。

 

  另一方面,从可适应性计算、网格计算到云计算,除了硬件资源的集中使用外,企业更希望操作系统、数据库,以及软件、应用等都能通过集中调配的方式满足企业的各种需求。随着互联网技术的迅速发展与普及,SOA则能带来整个软件系统的互联成本、维护成本、升级成本的大幅降低,并成为支撑云计算的技术标准。

 

  所有因素都帮助促成了从硬件层的基础架构云(IaaS)到平台云(PaaS)再到软件应用云(SaaS)不同层次的云计算。

 

SOA 与SaaS合力,推动云计算产业的成熟与发展

  云计算实现了IT基础设施的社会共享;SOA有利于整合技术平台,统一技术标准,推动软件产业价值链中的各成员间的协调配合,充分利用硬件资源共享的有利条件,促使云上的软件系统日趋成熟;SaaS则通过软件交付模式上的创新,为云计算开辟出更大的市场空间,激励众多软件厂商开发出更多应用,从而使云计算产业联盟不断发展壮大。

 

  总而言之,在云计算产业链向前推进的过程中,如果我们能善于发挥SOA和SaaS两者的特点与优势,将其效用结合起来,那必将有助于实现云计算产业的新一轮高速发展。

 

 

 

 

SOA如何拯救复杂的企业数据?

本文中我们将重顾一个典型的SOA架构,概述处理企业数据的复杂性,并讨论几种将数据整合进入SOA实现的设计模式。
 
1.介绍

今天,大多数SOA设计技术1,2,3 都是以定义服务为中心的。它们使用面向服务的分解原则,以业务流程为基础、企业业务/功能模型,要求的长期架构性目标和现有企业功能的重用。这种方法通常将现代企业最重要的资产之一——企业数据事后整合。

 
2.典型SOA实现

一个典型的SOA设计方法导致以一种专用层的形式实现企业服务,这个层次基于“理想的”企业业务模型3对现有企业功能(应用)进行了合理化处理。


这样的架构(上图)定义了SOA架构中的多个层次4: 

  • 企业资源和操作系统层。这一层描述了现有应用系统的业务职责。(即,遗留系统,COTS和用户自己构建的系统)。

  • 集成层。这一层使用不同的技术暴露现有企业资源和操作系统,这样它们就可以被业务组件使用。

  • 业务组件层。企业业务组件是可部署的软件单元,它提供业务服务需要的功能。这些组件可以是刚刚被开发出来的,或是使用集成层去访问现有企业资源“包装器”。

  • 业务服务层。业务服务提供整个企业的高级业务功能。这一层有效地嫁接了“理想”业务模型和现有企业IT资产——应用系统和业务组件。

  • 业务流程层。业务流程允许通过编制业务服务来创建业务解决方案。

  • 客户体验层。客户体验提供对客户(包括企业内部和外部)的支持,客户可以浏览和控制企业业务流程和/或服务的执行。这些客户可以是使用WEB或富客户端的人,或者是支持企业内部业务流程的B2B连接。

为了加强服务的跨平台的互操作性,这样的架构通常定义语义消息模型——企业范畴的业务对象,它们被服务接口定义使用。这些语义消息模型一般从相同的企业业务模型(被业务定义使用)中派生出来,因而确保所有的服务调用使用一个“通用语言”。结果是,典型的SOA实现有效地引入了两种不同的数据模型5 ——被服务接口暴露的“外部数据”和被服务实现使用的企业数据——“内部数据”。

 
3.企业数据存取问题

尽管典型的SOA实现在服务接口后面隐藏了企业数据,它仍然需要解决下面的数据存取问题:

  • 统一多应用系统间的数据。今天的企业数据一般分散在多个应用“竖井”中。每个应用系统仅仅包含企业数据的一个子集(仅限于应用要解决的问题),这些数据在应用系统之间常常存在重复。这种应用间的数据冗余造成了不准确的企业数据描述,以及应用间需要的定期数据同步,这些应用的每一个都是特殊功能/单元的“主”数据存储。此外,数据描述自身也因应用的不同而不同。这导致通常很难去调和单个应用系统的数据描述。随着单个应用的独立发展和进化,问题变得更加复杂。在一个SOA实现试图去表述企业范围的功能时,它需要操作基于一个定义良好的企业数据模型去进行操作。这意味来自服务实现企业数据存取,需要正确地调整和统一来自多个现有应用的数据,并且确保将数据变化传播到所有使用这个数据的应用系统中。

  • 服务对企业数据的所有权。现代服务定义技术的基础——功能分解不能方便地映射到企业数据上。例如,客户(以及对应的数据)的概念通常被多个功能性服务共享。问题在于功能和数据的分解完全由不同的规则驱动。功能分解是基于企业业务流程——企业功能;然而,数据分解基于企业数据的分类法——企业数据模型的基础。这导致将企业数据向企业服务调整变成一项令人怯步的任务。

  • 接口定义。因为服务调用总是远程的,服务设计倾向于大粒度接口,旨在最小化服务消费者和提供者间的服务流量(对话)。另一方面,依照数据存取的需求,需要高和细颗粒度的接口。最后,数据存取一般实现纯的CRUD(创建、读取、更新、删除)a功能,作为对企业服务实现业务有意义的接口,比如费率策略等。

 
4.SOA实现整合企业数据的模式

有好几种设计模式旨在使SOA实现支持企业数据,其中一些是已经广为认知,另一些则是刚刚兴起。下面我会描述三种最重要的。

1
 
使用业务服务协调企业数据支持

这是今天SOA实现的主流模式,与所有的SOA实现都合作得很好,如前面所示(图1)。在这个模式里,企业数据存取已经合并到业务服务实现中。数据通过集成层存取,服务实现自身负责定义和支持对特殊数据集的验证、存储、检索规则。这个设计模式的优点是能与所有的服务实现方法合作得很好。这个模式的缺点是:

  • 服务实现不得不除了支持服务的业务功能之外,还需要支持所有的数据验证、存取和协调逻辑。这导致业务实现经常和数据存取以及转换的代码纠缠在一起。

  • 在多个企业业务服务间共享业务数据需要额外的设计考虑,而且一般导致额外的企业服务间耦合。如果多个服务需要对企业数据的相同部分进行存取,可能使用下面的解决办法:

    • 在多个服务间复制数据存取逻辑。这允许每个服务独立存取数据,但是需要在多个服务实现间复制数据存取、转换、同步逻辑。尽管,理论上在有可能在一个单独的组件上封装这些逻辑,以便被多个服务重用,但是实际上几乎不起作用。多个服务实现平台,比如J2EE VS. .Net VS 主机,需要这些组件的不同实现。此外,因为组件不是独立可部署的,该组件的每次变更都需要将依赖它的所有服务重新部署。

    • 扩展一个服务的接口来包含操纵由服务控制的数据的CRUD方法。这个方法导致服务方法粒度的下降,抹杀了服务方法的业务意义。它还额外造成了企业服务间多余依赖,破坏了它们自治的本质。

事实上许多SOA实现都混合使用了上述两种方法。尽管这种模式一般适合小规模初级的SOA实现,但是对于企业级别的实现,它的扩展性不是很好。

2
 
将企业数据存取封装为业务服务

克服上一个模式缺点的一种方法就是将企业数据存取当作第一级的业务服务。在这种方式下,业务服务的一种特殊类型——数据服务——封装了所有企业数据存取、同步、验证、转换需要的逻辑。这个模式的优点是: 

  • 服务功能(业务逻辑)的实现和企业数据支持逻辑的实现在关系上的明确分离。企业数据服务有效地创建了一个抽象层,使业务功能避开数据存取细节。

  • 通过将非常稳定的数据存取代码从服务实现中分解出来,获得更佳的实现划分。

  • 类似其他业务服务,数据服务的接口通常也基于企业语义模型。通过业务服务大大简化了企业数据的消费。

这个模式的缺点是:

  • 因为企业数据大多数来自于企业应用系统,数据服务的实现将一般类似业务服务的实现——它由实现数据存取逻辑的组件和使用集成层来存取存在于现有应用系统的数据的组件一起构建。这使得常常很难区分以功能重用为目的的集成和以企业数据存取为目的的集成。企业数据存取集成,一般不会直接依靠企业数据存储——在数据存取和验证时,它们通常利用已有的遗留实现。这导致通常不容易把一部分实现归为单纯的数据服务或者业务服务。

  • 正如我们上面提到的,一个典型的数据服务接口设计是CRUD,它被认为是服务接口设计的反模式6。此外,因为数据服务需要支持一个范围广泛的企业数据存取选项(被业务服务所需求的),它们必须具备高度的灵活性。这些需求通常反映在数据服务接口的低粒度上。

  • 通过专门的数据服务集中化所有企业数据的存取要求业务服务的所有数据存取也通过这些数据服务完成。这样的实现导致完全的“聊天式(chatty)”实现,造成在数据服务上业务服务的强依赖性,这会一定程度上破坏服务的自主权。最小化这些依赖的一个方法是创建服务流程(组合服务),它管理基础服务需要的所有企业数据,将所有需要的企业数据当作一个参数集传给业务服务。尽管这个方法改善了业务服务的自主权,它通常导致流程状态和服务消息的“膨胀(bloating)”,对业务流程的伸缩性和服务调用性能有负面影响。

3
 
企业数据总线

今天SOA实现最流行的方法之一是使用企业服务总线模式7,它允许“虚拟化”企业服务存取b。 同样,企业数据总线允许虚拟化企业数据存取。从大多数方面来说,这个模式类似上面描述的企业数据存取服务。与将数据存取提升为第一级的业务服务不同的是,在这个方法中,这个模式作用在集成层上,它提供了任意服务直接访问企业数据任意部分的功能,如图2。


企业数据总线的起源可以追溯到数据库联邦技术——虚拟化存取企业中的异种数据库。不幸的是,这个技术对于SOA实现几乎不具有可应用性。这儿的问题是现有应用通过实现数据存取和验证逻辑有效控制了企业数据的访问

绕过这些应用系统直接访问数据库,需要重新实现这些逻辑,一般说来这很不划算。结果是,数据总线一般由集成层(图1)实现。市场上的新产品,例如IBM Information Server8就支持直接数据库存取和集成两种方法。这种产品通过“搭配”集成解决方案和直接数据库存取c,扩展了企业数据总线实现的灵活性。有效地实现这种模式,需要将提供企业数据存取的集成和提供企业功能能力的集成进行分离。考虑到数据和功能集成两者都获取/返回企业数据d,最直接的方法是考虑所有的集成都作为数据存取集成e。这导致SOA实现的全面修改。(图3)


这种实现(上图)增加了额外的一层——企业数据总线,它提供对包含于企业应用或是应用下属数据库中的企业数据的存取。这也修改了企业组件层的实现;在这种实现中它不再包含“包装器”组件。这种情况下,业务组件将仅仅由基于现有功能实现的服务功能组件和使用企业数据总线的数据存取组件组成。这种模式的优点是:

  • 服务功能(业务逻辑)和企业数据支持逻辑的实现在关系上的明确分离(和上一个模式相似)。企业数据总线有效的创建了抽象层,使业务功能避开企业数据/功能存取的细节。

  • 通过封装对企业数据/功能的所有访问,企业数据总线给所有的企业语义数据模型和企业应用系统的数据模型间的转换提供了一个单一位置。

  • 这种情况下,因为任何服务实现能访问它需要的任意企业数据,这样的实现允许显著地减少服务间的耦合——服务调用仅仅包含极少变化的数据引用(键),而实际的数据存取由使用企业数据总线的服务自身来实现。这意味着如果服务实现需要用于它的流程的额外数据,它可以在不影响它的消费者的情况下直接存取到数据。

这种模式的缺点是:

  • 由于大量的存取(同步),性能成为企业数据总线最重要的指标之一。总线上任何的一个性能下降,都会大大破坏SOA实现。

 
5.结论

随着SOA实现的范围从局部部门级实现扩展到企业范围,企业数据存取迅速成为最重要的实现问题之一。 如果每次一开始都不能正确的架构,企业数据存取将成为一个主要拦路虎。本文中展示的设计模式定义了在SOA环境中处理企业数据的不同方法,以及每个方法优缺点。

 

 

 

 

当“工业4.0”撞上SOA,duang~~堪比特效!

【编者按】在德国“工业4.0”的概念提出之后,德国将工业4.0视为生产重回欧洲的重大机遇,希望借助工业4.0,牢牢掌控对全球智能制造业的话语权。目前在中国也炒的很热,各方面都在解读工业4.0的战略意图及内容,或者在谈和两化融合发展理念、路径、目标的一致性。工业4.0战略的核心内容是什么?前段时间看到工业和信息化部电子信息司副司长安筱鹏的一篇文章“工业4.0——为什么?是什么?如何看?怎么干?”个人认为这篇文章非常全面的解释了工业4.0的内容。当然,“工业4.0”不同的人从不同的维度来解读的话,会有不同的理解,它涉及到国家战略、产业战略、企业发展等不同的层面。就从企业的层面去研究,我们看看企业层面实现工业4.0该怎么做,怎么走,有没有路线图?这里把工业4.0战略要点概括为:一个网络、两大主题、三项集成、八项计划以及大数据分析。

 

当“工业4.0”遇上“中国制造”

 

近期,随着“工业4.0”的在网络上越炒越热,我国也推出了“中国制造2025”战略,在国家战略需求的驱动下,中国对于制造大国向制造强国的迈进之路也陡然提速,这将对中国制造转型升级打通主动脉。就企业层面来说中国版工业4.0如何落地将成为重点,如何通过信息技术和制造技术的深度融合,打通一切、联通一切是企业信息化建设的目标。

 

工业4.0与SOA的关系?

 

忽悠?质疑?—— 这可能会是大家看到这个题目的第一感觉,这两个风牛马不相及的名词怎么会有联系呢?本人从事制造业信息化建设工作二十多年,经历了制造业信息化的各个阶段,近几年研究实践SOA架构在制造企业信息化建设中的落地,有一定的经验和总结,同时,近期也随大潮解读了工业4.0战略内容,发现工业4.0战略目标中需要实现的CPS信息物理系统、三项集成与我们从事SOA实践的一些实际应用案例及思想有异曲同工之处,SOA不仅和工业4.0有关系,而且不失为工业4.0目标实现的一种最佳技术手段。

 

我们知道很多企业处在工业2.0、工业3.0、工业4.0并存的状态,有老式的非智能的生产设备,也有最先进的智能化设备在同时使用,我们不能一下子把老式的设备都淘汰掉,这样如何实现工业4.0提出的智能化工厂呢?我们需要在老设备进行技术改造,保留其基础加工能力,加装传感器、PLC控制器、RFID等,这样就能把老式设备改造成一个加工服务单元,集成到信息网络中,与智能的新设备一起提供一个组合式的服务,各种设备之间的服务相互连接和协作,并与管理信息网络互通,从而形成一个智能化的生产线、智能化的工厂,这就是SOA思想在工业4.0中的体现,这样两者之间就有关系了啊。

 

 

在工业4.0蓝图中,连接一切的信息物理网络(CPS)是实现智能工厂、智能生产的基础,工业4.0蓝图给了一个CPS网络的概念模型 ,在这个模型中,我们看到了“服务”的概念,传感器服务、控制服务、通讯服务、校验服务、信息服务等,所有的服务形成了一个服务库,每个服务完成不同的功能,服务与服务之间相互连接,构成一个柔性的智能生产网络,每个服务来自不同的系统,产品信息服务也许来自PDM系统、生产计划服务来自ERP、订单服务来自DMS系统,生产装配指令服务来自MES、生产加工服务由设备完成,因此,整个CPS网络系统就是一个服务连接的网络,即是“务联网”的概念,通过“服务”的抽象,屏蔽了各个信息系统及物理设备的差异性,在服务层面具有共通性,因而容易建立起连接。

 

服务的概念即是SOA的核心,SOA即是解决异构系统、设备、网络相互连接的技术方法,通过SOA中的企业服务总线ESB建立起一个企业的“同声翻译平台”,让企业中的异构系统、生产设备、人、客户相互联通,让这些生产要素协同工作而又保持各自的个性化特征,各要素按照自己的方式工作,通过ESB这个同声翻译平台接收信息、指令,同时将自己的状态、信息发送到ESB平台、传递给其它生产要素,从而实现智能的感知和协作。

 

CPS 网络模型是一个理想的参考架构,在CPS网络模型中并没有给出怎么解决异构系统及设备间的连通性问题的技术实现方法和路径,我们都知道,对于具体的企业来说,要实现工业4.0的蓝图目标,有很多实际的困难要解决,企业的信息系统都是在不同的时期建立起来的,采用了不同的技术路线,由不同的厂商提供,技术协议不同,不能直接联通,需要点对点的写接口程序才能联通。对于生产设备,差异性就更大了,老式的设备没有通讯接口、仪表都是模拟的,新式设备的通讯协议及接口也是五花八门的,有RS232,485,以太网等,即使有相同的接口形式,其数据格式和规则可能都不一样,如果要将这些设备连接起来,一些老设备需要加装传感器、PLC控制器、RFID等,构建一个工业总线,将这些新老设备通过各种接口接入到工业总线中,使其相互联通、采集设备的数据,搞工业自动化系统的人都知道,工业自动化系统一般都遵循一个行业的标准协议:OPC,是一个比较底层的协议,一般大家熟知的SCADA系统、DCS系统都是这类性质的工业自动化网络,现在叫做“物联网”。工业自动化系统的运行方式与管理信息网络的运行方式完全不一样,数据生成的频率要高的多,一般以秒为单位生成数据,数据存储的方式也不一样,数据一般是以KEY/VALUE的方式收集和存储,俗称列存储方式,而管理信息系统,如ERP、PDM等系统的组织存储方式是以行的形式存在的,数据交换的协议以SQL、webservice、FTP、MQ、HTTP等更高级的协议通讯。所以要实现工业网络与管理信息网络的相互联通,从底层网络协议上容易实现,但是要实现数据的交换还不是那么容易,所以工业4.0中才提出了CPS网络的参考架构,力图实现“连接一切”的目标。

 

下面我们参考一下SOA架构下的ESB企业服务总线架构模型,看看能不能满足CPS的要求。

 

 

我认为,这就是一个CPS网络系统的模型,一个可以落地的参考架构。ESB企业服务总线是SOA架构的核心,完全满足CPS的要求,它通过各种适配器与异构系统和生产设备相连,进行协议转换,数据交换通过消息的机制实现,通过消息的异步传输达到数据交换的可靠性,可以实现数据的同步及异步交换,在电信、银行、铁路、航空、电力调度中广泛应用,是一个非常成熟的数据交换平台解决方案。S0A架构是一个已经非常成熟的架构方法,实际应用已经很多年了,以前只是从纯粹的技术层面来推广,没有站在产业战略的高度来看这个问题,应该说SOA是工业4.0最佳的技术方案。

 

三个集成

 

工业4.0中的三项集成包括:横向集成、纵向集成与端对端的集成。工业4.0将无处不在的传感器、嵌入式终端系统、智能控制系统、通信设施通过CPS形成一个智能网络,使人与人、人与机器、机器与机器以及服务与服务之间能够互联,从而实现横向、纵向和端对端的高度集成,集成是实现工业4.0的重点也是难点。

 

【纵向集成】

 

纵向集成不是一个新话题,企业信息化发展经历了部门需求、单体应用到协同应用的一个历程,伴随着信息技术与工业融合发展常讲常新,换句话说,企业信息化在各个部门发展阶段的里程碑,就是企业内部信息流、资金流和物流的集成,是在哪一个层次、哪一个环节、哪一个水平上的集成,是生产环节上的集成(如研发设计内部信息集成),还是跨环节的集成(如研发设计与制造环节的集成),还是产品全生命周期的(如产品研发、设计、计划、工艺到生产、服务的全生命周期的信息集成)。简单点说,纵向集成就是解决企业内部信息孤岛的集成,工业4.0所要追求的就是在企业内部实现所有环节信息无缝链接,这是所有智能化的基础。

 

纵向集成主要解决企业内部的集成,即解决信息孤岛的问题,解决信息网络与物理设备之间的联通问题。

 

【横向集成】

 

横向集成是企业之间通过价值链以及信息网络所实现的一种资源整合,是为了实现各企业间的无缝合作,提供实时产品与服务。在市场竞争牵引和信息技术创新驱动下,每一个企业都是在追求生产过中的信息流、资金流、物流无缝链接与有机协同,在过去这一目标主要集中在企业内部,但现在远远不够了,企业要实现新的目标:从企业内部的信息集成向产业链信息集成,从企业内部协同研发体系到企业间的研发网络,从企业内部的供应链管理与企业间的协同供应链管理,从企业内部的价值链重构向企业间的价值链重构。横向集成是企业之间通过价值链以及信息网络所实现的一种资源整合,为实现各企业间的无缝合作,提供实时产品与服务,推动企业间研产供销、经营管理与生产控制、业务与财务全流程的无缝衔接和综合集成,实现产品开发、生产制造、经营管理等在不同的企业间的信息共享和业务协同。

 

横向集成主要实现企业与企业之间、企业与售出产品之间(如车联网)的协同,将企业内部的业务信息向企业以外的供应商、经销商、用户进行延伸,实现人与人、人与系统、人与设备之间的集成,从而形成一个智能的虚拟企业网络。制造业普遍存在的工程变更协同流程就是这样一个典型的横向集成应用场景。

 

【端到端的集成】

 

端对端集成是指贯穿整个价值链的工程化数字集成,是在所有终端数字化的前提下实现的基于价值链与不同公司之间的一种整合,这将最大限度地实现个性化定制,从某种意义上来讲,端到端的集成是一个新理念,各界对于端到端集成有不同的理解。

什么是端到端?顾名思义,所谓端到端就是围绕产品全生命周期,流程从一个端头(点)到另外一个端头(点),中间是连贯的,不会出现局部流程、片段流程,没有断点。从企业层面来看,ERP系统、PDM系统、组织、设备、生产线、供应商、经销商、用户、产品使用现场(汽车、工程机械使用现场)等围绕整个产品生命周期的价值链上管理和服务都是整个CPS信息物理网络需要连接的端头(点)。

 

端到端集成就是把所有该连接的端头(点)都集成互联起来,通过价值链上不同企业资源的整合,实现从产品设计、生产制造、物流配送、使用维护的产品全生命周期的管理和服务,它以产品价值链创造集成供应商(一级、二级、三级……)、制造商(研发、设计、加工、配送)、分销商(一级、二级、三级……)以及客户信息流、物流和资金流,在为客户提供更有价值的产品和服务同时,重构产业链各环节的价值体系。

 

由于整个产业生态圈中的每一个端头所讲的语言(通讯协议)都不一样,数据采集格式、采集频率也不一样,要让这些异构的端头都连接起来,实现互联互通、相互感知,因此就需要一个能够做到“同声翻译”的平台,这个同声翻译平台就是企业服务总线,在这样一个平台上实现书同文、车同轨。这样就解决的集成的最大障碍,实现互联互通就容易了。

 

端到端的集成即可以是内部的纵向集成内容,也可以是外部的企业与企业之间的横向集成内容,关注点在流程的整合上,比如提供用户订单的全程跟踪协同流程,将用户、企业、第三方物流、售后服务等产品全生命周期服务的端到端集成。

 

横向、纵向、端到端三个集成的实现,不论技术层面还是业务层面在SOA信息集成都能找到相应的解决方案。

 

SOA如何实现工业4.0三项集成

 

首先我们先来看看SOA架构的内容,看是否和工业4.0战略架构相匹配,SOA核心架构包含三个层面(界面、流程、数据),如下图所示:

 

第一层:门户(界面)

 

门户是用户接入的端口,解决信息访问接入的问题,提供多种设备接入的协议,包括手机、IPAD、PC等终端设备,是信息集聚、人员集聚、流程集聚的协作平台。门户可以为工业4.0蓝图目标提供对内对外的协作平台。

 

第二层:BPM业务流程管理

 

BPM业务流程管理实现跨系统、跨部门、跨企业的端到端协同流程的驱动。BPM流程平台可以为工业4.0蓝图中的三个集成提供纵向集成、横向集成和端到端集成目标的流程驱动。

 

第三层:ESB企业服务总线

 

企业服务总线解决异构系统、设备的接入问题,提供各种适配器连接设备及系统,进行通讯协议的转换,提供数据交换服务,可以为工业4.0中的CPS系统解决连通性的问题,从而构建一个可以连接一切的网络。

 

 

上图是SOA架构与CPS网络架构的一个完整框架,从这个图中,我们可以找到工业4.0智能生产网络中的所有要素以及他们之间的关系。其中SOA架构中的核心层门户、BPM、ESB是实现工业4.0的三个集成目标的基础支撑平台,是三个层面的服务组件的容器及承载体,有了这三个平台的支撑,才能实现企业的纵向集成和横向集成,以及端到端的集成。

 

 

【案例】国内某汽车制造企业——CPS及三项集成的实现

 

该汽车企业的IT系统经过20多年的建设,ERP、PDM、CRM、HR、MES、WMS、OA等都已经建设,加上各个基地的本地化系统,该汽车集团有60-70多个系统,这些单体系统的建设实现了部门信息的共享和协作,但是孤岛现象严重。随着业务的发展,异地协作、跨供应链的企业协作已经成为集团业务发展的一个瓶颈,因此实现工业4.0战略中的三项集成和信息物理网络是当前该汽车企业IT建设规划的一个重点,连接一切、集成一切是该企业当前IT实现的一个战略目标。

 

2012年该企业开始论证内部的纵向集成及集成服务平台的可行性,2013年开始实施建设,该项目从数据层面的集成开始做,通过近两年三期的建设,已经集成了20多个系统,实现了多个基地与总部,总部与银行之间的互联互通,按照业务规则交换的数据每天达到3万笔,为各个业务系统、业务板块的实时协作发挥了重要作用。下一步,该企业计划将接入更多的系统及欧洲基地的系统,并建设门户系统、BPM系统,车联网系统,从而实现横向集成、端到端的流程集成和实时协作,最终实现智能生产和智能工厂。

 

下图为该汽车企业集团三项集成的规划,是值得学习的一个案例。

 

 

一期:制定集团集成标准化规范,建立服务目录。实现ESB平台核心框架的搭建,通过RFC、MQ等适配器方式将总集团核心系统,生产SAP、销售SAP、SRM、动力MES、DMS、集团QNS、整车QNS应用系统等接入总线平台。统一的监控管理平台已经建设完成,可以全面监控管理系统之间的交互情况。

 

二期:在一期的基础上,完成全面预算项目相关系统的集成(预算系统、BO系统),WMS项目相关系统的集成,完成海外协同项目、KD项目相关系统的集成;

 

三期:完成基地WMS、EWM、SRM、QNS、MES系统的集成。

 

四期:完成经营体、企业级BOM平台、车联网、CEVT银行等的集成。

 

后续项目:在前期企业服务总线建设的基础上,2015年,将实现协同门户,端到端的业务流程集成整合,持续打造该汽车企业智能工厂和智能生产,在不久的将来,该汽车集团将会提供用户直接网上的个性化汽车配置,全程监控汽车完整的生产过程,实现汽车商品的个性化定制。


下图为该汽车企业CPS网络架构图:

 

 

由电子工业出版社出版的《自主变革的基石---制造业管理技术及SOA实践》、《面向服务的企业应用架构---SOA全息架构及特色》两本书是作者参与著作的,是关于实现工业4.0的CPS和三项集成最佳技术SOA架构规划及SOA在制造企业变革中的最佳实践。该两本书既有技术层面的解答,又有业务层面的案例分享是作者多年制造业信息化经验的总结。

工业4.0时代,中国制造企业该如何去思考?请阅读系列文章和技术指导参考书,相信这些经验之谈和实施案例分享能够帮助你拓展思路!

 

 

 

 

从SOA说起,谈谈我对服务的理解

 

service-origin-exploration.pdf
PDF-Dokument [6.3 MB]