电子说
SOA: Service Oriented Architecture, 面向服务的架构,或者说,以服务为基础搭建的企业IT架构。SOA中服务(Service)的理念,本质上是一种业务和技术完全分离,业务和技术又能自由组合的思想。 它达到了目前软件设计思想的最高境界。
增强现实导航软件运用到了SOA框架,提供的SOAP接口可以满足不同语言不同平台的调用,采用HTTP协议,Http协议是跨平台的协议,因此在安卓端和后台交互上无疑是比较好的选择。
SOA有3个基本的要素,只有这3个基本要素全部都满足了,这个应用才能称为SOA的编程:(1)松散耦合;(2)粗粒度;(3)位置和传输协议透明。
(1)松散耦合是指相互之间的依赖程度,包括三个方面:1)服务之间的松散耦合: 不同服务的功能不要互相依赖, 相对独立而完整,所谓自包含;这样就比较好管理各个数据2)接口和实现之间的松散耦合: J2EE或.NET只需WSDL就可以调用WEB SERVICE的服务接口;3)业务组件和传输协议之间的松散耦合:传输协议和位置的透明。 (2)粗粒度的意义是SOA中服务的接口应该比面向对象的编程的API要大一些。以ATM取款机的取款功能来说明这个问题。取款功能的实现可能实际要包括下面的3个API:1)身份校验: 系统确认用户输入的卡号和密码是否正确;2)余额查询:账户是否有足够取款数额;3)取款: 以上两项都满足后,才真正付给用户现金。
ATM取款机取款功能的3个API
作为SOA的业务接口,就不能将“身份校验”和“查询余额”这两个API公布给用户,因为这样太细了。如果让用户必须操作完两个接口,最后再操作“取款”接口,则不符合用户的操作习惯。所以系统只能给出符合用户操作习惯的一个服务接口“取款”,它里面包含前面两个API功能 。
(3)位置和传输协议透明是SOA最根本的区别于目前面向组件编程的地方。目前的服务组件如EJB、WEB SERVICE、JMS的发布都是和特定的应用服务器绑定在一起的。如果某个服务组件的URL位置修改了,客户端程序必须要做相应的修改,否则整个集成不能工作了。这就是位置组件的不透明。
所谓位置的透明,就是指不论服务组件的实际位置URL如何变化,客户端的调用程序的URL都不需要改变。所谓传输协议的透明,就是指不管服务组件的传输协议如何变化,客户端的调用程序的传输协议都不需要改变。
SOA架构中有三种角色:(1)服务提供者Provider:发布自己的服务,并且对服务请求进行响应。(2)服务注册中心Agent:注册已经发布的web service,对其进行分类,并提供搜索服务。(3)Consumer服务请求者:利用服务中心查找所需要的服务,然后使用该服务。
SOA的三种操作:(1)发布操作:为了使服务可访问,需要发布服务描述以使服务使用者可以发现它。(2)查找操作:服务请求者定位服务,方法是查询服务注册中心来找到满足其标准的服务。(3)绑定操作:在检索到服务描述之后,服务使用者继续根据服务描述中信息来调用服务。
SOA实例:在石油企业内部,有许多不同的网站,进入每个网站,都需要身份验证,不仅浪费时间而且容易遗忘代码 ,另外,网站维护人员对各种服务需要建立相应的用户认证与信息管理系统,分布于个服务器中的用户数据不仅浪费维护人员的时间,而且过于分散的用户数据不利于统计和管理。用户的需求和管理要求促使用户趋于统一,产生了统一者认证。统一认证的实现是基于SOA的架构。
从中可以看出使用SOA的优点:将身份验证这一功能模块发布成一种服务,其他的软件可以通过UUDI查找该服务,然后将该服务与服务的实现进行绑定。
进行SOA类型的架构设计就需要搞清楚SOA架构模型才行。并不能想当然的对系统进行简单的拆分就行,需要搞清楚SOA的架构模型是怎样的,每一块是干什么用的,这样设计由分析阶段输出的需求时才能正确的划分职责。
如果把SOA的架构简单的理解为是多个子系统之间的整合其实有点太过于简单,也没有真正搞清楚SOA的架构模型。按照SOA的正确方法论及目标模型,其实SOA在实现架构落地上,需要考虑到对服务的组合,不断的重用现有的服务,让企业应用可以逐步集成,快速实现业务的迭代。其实这就是本节要讲的服务的分层,通过分层将服务按照使用类型进行分配,上层服务对下层服务的包装,下层服务负责原子性的操作,上层服务对下层服务进行业务性的组合。
我们来看具体的每一层的作用及主要职责。
1、应用服务(原子服务)
应用服务就是诸如:订单服务、仓库服务、销售服务、客户管理服务,这些服务直接对应不同的应用系统,直接服务这些应用系统的原子操作。订单服务直接原子性的插入订单,没有任何跨其他服务的分支逻辑。仓库服务只管自己的仓库逻辑。同样其他的应用服务只管好自己的职责,杜绝对其他服务的调用。
应用服务位于UI与后台之间,后台我们可以认为它是一异构的系统或者是数据库之类的。应用服务的位置位于前端与后端之间,起到类似一个服务API的作用,但是SOA中的服务还远远不止这一个应用服务,如果我们的SOA架构中只有一种类型的服务,那么这会增加我们系统的耦合程度,因为你没有对系统的服务进行层次的划分,你的业务功能会直接的落到某一个应用线上的服务,继续往下看。
2、组合服务
组合服务是对应用服务的一个组合,根据实际项目的规模大小,不一定非要进行物理的隔离,在代码层面的服务化也是可以的,在将来的某一天有必要的情况下再进行物理的拆分,毕竟物理的拆分有着严重的成本和代价,对系统的稳定性带来很多挑战。所以经验告诉我们必要的时候在进行拆分。”分布式系统设计的第一个原则就是尽量不要分布式“,这是马丁。福勒大师说的,现在理解确实感同身受。
组合服务对下层的应用服务进行了组合,完成了一个基本的业务动作,应用服务中是最基本的基础性的原子性的操作。但是在复杂的业务需求下大部分业务功能都需要跨越多个应用线来完成一个最外层的企业动作。提交订单可能需要穿过很多应用线,订单管理、仓库、财务等等环节。所以这里我们还需要一个能在最外层对组合服务进行编排的业务服务。这个编排服务可以完全是自动化的,通过工作流引擎进行组合自动化来完成,这对企业应用的自动化流程很有意义。
3、业务服务(编排服务)
业务服务是最外层的服务,向下编排了组合服务。业务服务位于最上层,当需要有跨越多个应用线来完成的业务,这个业务就放入业务服务中。比如提交订单,先检查库存、扣减库存(冻结库存),然后下单,再往后通知财务,再往后通知物流等等都是一个复杂的企业服务线。这种最外层的业务逻辑如果你不进行SOA分层然后将其放入最外层的业务服务中,你把它放入任何一个应用线都会使系统调用混乱不堪。所以问题就是需要进行纵向的划分层次。如果进行了SOA的层次划分后就不会出现互相乱用的情况。其实这里可以参考阿里的服务设计方法。(李智慧写的一本大型互联网架构与实践里面也讲到了服务要划分层次)
当在业务服务中执行的业务逻辑时,需要跨越多个应用线来完成。这部分的逻辑也说是职责,如果不放入这个位置,放在哪个应用线都不合适,放入哪个应用线都会使系统调用出现混乱。其实这里的问题就是我们不能用一个维度来进行SOA系统的设计,本来服务就具有组合特性,所以适当的提升服务的层次是有好处的,但是应用服务和组合服务可以在代码层面上进行构建,而业务服务也叫编排服务是需要进行物理隔离的,毕竟考虑到系统复杂度和稳定性问题这是值得的。在排查问题,系统性能、稳定性等等方面,物理的隔离有一定的作用,毕竟业务服务本来就是来组合多个应用线的,这样做会使整个系统架构很清晰。
进行SOA化的实施,大部分情况下都是对现有系统进行重构后考虑的,初期企业发展阶段以快速出原形为首要目标,只有当系统出现瓶颈了才会考虑运用SOA来解决。但是在这个时候有很多历史包袱无法解决,进行SOA化的重构其实成本是很高的,而且很危险,对有些复杂的逻辑说的现实点,是无能为力的。如果都可以通过重构这个技术来解决,那我们就太天真了。《重构—马丁。福勒》一书讲的是代码层面的重构,跟做系统级重构两个概念。对系统级别的重构还没有太多成熟的方法论支撑。尤其现在新技术层出不穷的,各有优点,能很好的运用这些技术、方法论、过程来重构大型企业级系统,难度非常大,这需要整个公司投入很多人力、资源成本。回过头来想想,其实在前期适当考虑一下还是有必要的,这样可以减少后期很多技术债务。
这里我只总结我在分析、设计公司某一块业务系统的时候对其进行SOA化的重构思路。重构本来就是一个不断迭代的过程,不可以跨大步。通过很多脚手架支撑,让系统慢慢的过度到新的SOA架构下,既然要实施SOA架构,那么很重要的一点就是对迁移的业务逻辑适当的归类,什么业务逻辑该放入“业务服务”中,什么逻辑该在代码层面上放入“组合服务”中,对基本的操作有如何放入代码层面的“应用服务”中。
1、保留服务空间,为了将来服务的组合
在进行系统拆分的时候,对当前后端的调用都进行适当的规划,将其分为两类,一类是应用服务,一类是组合服务,这两个服务是可以在代码层面上进行抽象。重点是那些调用其他系统的地方,需要将其放入业务服务中,这块逻辑比较复杂,难以抽取,需要适当的结合”数据落地“的思路来综合考虑。有时候把一部分数据落入本地可以提升系统的整体简洁度和稳定性,但是要考虑数据的一个生命周期性质。
在迁移的过程中可能还会有一些新的功能并行开发的,既有新的逻辑需要放入新的SOA服务中,也会有迁移过来的逻辑,这两个过程同时进行其实很痛苦,尽量避免这样同时进行,但是现实是根本不可能,正常都是一起并行推进。如果这两个过程是同一组团队负责其实还好,毕竟对这块的代码、业务都比较了解。
这一节目的是想强调对现在系统进行迁移的时候要考虑服务的层次,不要只进行一个简单的搬移代码,这个时候是一个对代码进行重构的好机会,该划分层次的要划分层次,该读写分离的要读写分离,要重点考虑那些“业务服务”,需要跨越多个应用线的逻辑。
顺便说一下,还有一个重点就是迁移的时候还要考虑数据存储方面的迁移,光代码层面的迁移只是第一步,第二步还需要进行数据层面的迁移。当然这两个大的步骤都是要通过很多次迭代完成,并且还是一个对业务、代码进行很好梳理和整理的好机会。
在将系统进行服务化的时候要考虑服务层,如果当前没有业务服务的逻辑那么就保留服务空间,至少要清楚在服务层中有这么一个空间是要预留的,当有其他的应用线需要与你交互的时候可以顺利的进入到你的服务区,而不是直接到达你的应用。
做系统设计时最怕的就是职责搞错了,这会使系统的架构突然就复杂了,而且系统架构都是很难改变的或者压根就无法改变的决定。所以我对这块引起了重视,有时候你对业务在了解在熟悉依然会搞错职责,对于这块光凭主观的判断是不长远的,无发复制、无法传播的,也无法落字成文的。
对DDD我这里就不多做介绍了,这里要强调是GRASP。运用DDD可以很好的帮助我们来战略性的观察企业所坐立的领域,我还是很提倡DDD在公司实施的,不说DDD中的“战术设计”方法论,就光说它的“战略设计”方法论还是有很大作用的,让我们可以在脑海中建立一个战略性的模型。具体要不要进行代码层面的落地这就看实际情况了。而且DDD中的很多不错的思想都可以借鉴过来,包括领域通用语言,有了领域通用语言团队之间的沟通和交流会节省很多成本。对于新人来说,可以很快的了解公司的一些大概的业务,这和“词汇表”其实还是有区别的。
上面说了,在划分职责的时候很多都是通过经验来主观的判断,没有其他的客观证据了。那么有没有一个不错的方法论或模式来指导我们进行这类问题的解决呢,其实还是有的,因为在国外人家这方面已经很成熟。
GRASP就是这样的一套模式,它可以帮助我们进行客观的设计职责。到底该把这块数据放入哪个应用中,到底该把这个逻辑放入哪个服务中,都有指导,包括对对象层面的设计依然可以。我们可能对“信息专家模式”都有了解,但是以往我们可能都只把它用在对象设计上,而没有提升一个系统层面中考虑。那是因为我们以往可能没有碰见很复杂的职责分配场景,只有当出现问题时我们才能真正领会某个东西的好坏。
DDD只有结合GRASP才能客观准确的方配某个领域的职责,不管是战略设计层面还是战术设计层面,都是一个很好的平衡标准,不会由于技术人员主观的兴趣倾向导致一个错误的职责分配决定,而这个错误的决定最终是要开发人员来买单。
传统分布式系统与当代的面向SOA的分布式系统有一定区别,论概念上来讲SOA是以服务为中心,既然以服务为中心就会有很多面向服务的设计原则。而传统的分布式系统没有服务的概念,也没有所谓的一切皆是服务的原则。而当代SOA则首要原则就要以服务为中心,针对服务的设计又有了很多服务设计原则。
SOA对服务还进行了类型的划分,按照服务的应用层次来分类:业务服务、组合服务、应用服务,包装服务等。再按照管理与运维的层面来分类:控制服务、调度服务、监控服务等等。传统的分布式系统是没有这些的,我们谈论的是当代SOA的分布式系统,所以我们强调的是以服务为中心,以服务设计原则为架构设计的指导要求,当代SOA是对传统分布式系统的一个迭代进化,不是一个时代的产物,SOA更加强调了以服务为首要原则,已经提升到了另外一个更加高级的层面。
本节我们交流一下在当代SOA分布式系统中的数据一致性问题,在SOA中这主要涉及两个层面来考虑,一个是服务层面、一个数据持久化层面。再按照一致性的基本要求,可以分为:读一致性、写一致性、会话一致性、最终一致性、实时一致性等几个维度,当然还有其他几个维度的一致性要求。
我们这里重点讨论在企业应用中实施SOA时遇到的一些比较棘手的数据一致性问题和解决方案,对于刚才提到的几个维度的一致性要求均具有重要的参考价值。
1、分布式事务(基于DTC的分布式事务)
以往包括目前很多项目还是倾向于使用DTC来处理分布式事务,这个方案多数适用于一般的企业应用,业务、访问量、数据量要求都不是很高的情况下。用DTC很方便,事务的自动传播、事务的自动感知、事务的自动回滚和提交,这都是中央DTC帮我们管理好了。
由于有中央DTC的统一协调,看似好像帮我们解决了很多我们需要考虑的问题,但是它也是整个平台的致命的瓶颈,一旦DTC由于某个问题出现错误,而且这种错误都是系统层面的错误,很多问题我们是无能为力的。如果出现问题,整个应用平台都无法完成任何一个跨服务的业务流程,这其实很危险,你不无法控制系统的稳定性。
这里总结,DTC用于一般的小型企业应用,不建议用在中等规模的企业应用中,不是说这个东西不好,而是无法控制它。
2、事务补偿(提供正向或反向的操作来让数据在业务上是一致的)
世界级SOA专家所编写的书籍里都提到了使用“补偿”操作来完成数据的不一致性,当我们编写了一个服务方法A,就需要一个服务方法A1的补偿接口来完成A服务的补偿操作。但是真实的业务情况下很难实施这种看起来好像很优美很柔性的设计。没有实践就没有发言权,我们公司的技术团队就实施过这种方案,但是很不理想,这跟技术本身及技术团队没关系,只是我们的平台业务太复杂,很难去“补偿”一个已经做过的操作。
这当然也要看你所面对的项目情况,量变引起质变,如果你的各种量都上去了,这个“补偿”方案不实际,而且很难在数据层面进行“补偿“。总之,这不是一个中长期的方案。
3、异步EDA(基于异步事件流来实现柔性的分布式事务)
EDA简称”事件驱动架构“。多个系统之间通过传播”事件“来驱动整个业务的运转。系统之间没有紧耦合的同步调用的操作,都是通过发出异步的“事件”来通知下一个业务环节。
可能你会有一个疑问,异步操作,是不是系统之间延迟会很长,其实不是,现在有很多成熟的消息中间件在内网内几乎是毫秒级别的延迟,至于跨机房就看物理上的距离了。
异步操作有很多好处,这里我就不浪费大家时间重复那些好处。使用EDA实现系统之间的一个松散的事务关系,要把控好项目的质量,对系统的非功能需求、BUG数等等可能会影响业务操作中断的地方都要建立起适当的机制,让这些问题尽早的在线下解决。比如可以实施UnitTest、持续集成等一些敏捷的方法论。
同样一个工具在于什么人用,真正的工匠都是使用很朴实的工具来雕刻无法超越的艺术品,这就是工匠情怀。最近对工匠情怀感受越来越深,一直以为自己是一个比较喜欢专的人,这是不是偏离了一个大的方向冲进了一个小胡同,直到最近我才领悟,这其实是”软件工匠“的精神。但是这不代表不考虑全局,这只是一种情怀,一种态度,对于架构也是,对于代码也是,不要认为那些看似无关紧要的问题就忽视它,带着工匠精神雕刻它。
全部0条评论
快来发表一下你的评论吧 !