注:在网上看到这篇文档,觉得写得很好,清晰实用。该博客其它文章也写得不错
现在对于一个应用系统的开发,都在强调一个词即基于SOA架构或者叫符合标准的SOA参考架构,因此有必要对应用系统构建过程中如何才能称得上是基于SOA架构的进一步进行说明。
前面已经有很多文章谈到过,SOA思想的核心根据定义可以拆分为两个重要的内容,一个是根据业务建模和架构设计过程找寻到粗粒度的可重用的服务;其二是这些服务可以组合,可以组装和编排以满意业务流程的需求。前者重点对应的是ESB服务总线,而后者重点对应的BPM和BPEL相关业务能力。
对于一个基于SOA的架构的业务系统,应该符合以下这些最基本的特征:
首先是业务系统是组件化和模块化的,需要在业务系统构建过程中体现CBM和业务组件化,组件能力化的思想。一个完整的业务系统通过业务建模和架构分析应该根据松耦合的原则拆分为多个业务组件,业务组件最终转换为应用系统实现中的应用模块(服务组件+技术组件)。每一个组件都相对独立,都可以独立进行分析设计,开发,测试,部署和后续运维的管理。
在应用开发中,我们经常可以看到一个业务系统划分为多个模块,但是各个模块之间仍然是完全混乱的交叉调用,不符合松耦合的思想。也完全约束了各个组件可以完全独立部署和管理。同时虽然有时候进行了组件的划分,但是数据库没有完全拆分开,应用层和逻辑层划分了组件做了拆分,但是到了数据库又完全混在了一起,也导致组件模块之间无法拆离。
组件划分的粒度,组件应该内聚的功能需要仔细分析,这些是组件之间能够松耦合的基础。组件之间的交互或者说组件向外暴露的能力只能以服务的方式进行,这个服务需要满足粗粒度服务的基本特征。即对于服务的消费方完全不需要了解组件内部的实现逻辑和细节,而只需要根据业务场景调用组件朝外暴露的能力。
组件以暴露粗粒度服务为原则,能够使用组合服务的就尽量使用组合服务,不能使用组合服务的时候才使用更下层的业务和数据的原子服务。这些服务构成一个组件核心的领域层。但是要注意的是不是领域层所有的服务都需要朝外部暴露,而仅仅是涉及到跨组件交互的服务才需要朝外部暴露。在这里还要注意的就是暴露的服务是领域层的能力,而不是数据库级别的CRUD,我们很多时候看到为了减少服务的数量,全部暴露为通道形式的DAL类服务,这本身是完全违背原则的。
服务本身就是轻量的API,因此服务具体实现是采用soap webservice还rest或其它方式并不重要,重要的是服务接口和契约只要不变更,即对于消费该服务的模块就不应该造成各种重新编译或部署的影响,这些轻量API或服务需要达到的一个基本的要求。
其次,服务本身需要是可复用的,服务的目的不仅仅是为了解决组件间的交互,这仅仅达到了服务能够松耦合各个组件的目的。而为了满足服务的可复用性,即需要考虑在各个业务模块的基础上,应该有一个更加底层的提供共性能力的基础公共模块,这个模块提供共享的可复用的服务能力出来。
前面曾经谈到过对于业务系统一般分为两个大的类型,一个是数据驱动型的,一个是流程工单驱动型的。对于资产管理,资源管理属于前置;对于OA,ITIL类业务系统完全属于后者。而对于前者往往都有一个核心的底层共享数据模型,这个共享数据模块上层的业务模块都需要用到。这个底层则提供共享的可复用的能力。即使对于流程驱动的应用,往往也存在架构分析设计中识别出可复用的内容进行提取。
对于安全,消息,缓存,文件,日志,异常,4A,流程引擎等技术类组件,更加是所有模块都需要复用的内容,在一个业务系统中的设计中这些需要抽取为独立的技术组件,提供可共享的技术服务。如果在实现过程中再结合AOP的思想将更好,这样业务系统构建和实现过程中将更加简单。
再次,业务流程的实现或复杂业务逻辑的实现应该体现服务组装或服务编排的思想。在这里和是否使用BPM工具,使用BPEL没有太必然的关系。在这里不是指的工作流引擎自动处理的审批流,而更多的是指需要程序自动化处理的业务流或复杂业务规则。如资产调拨可能需要调用多个原子服务来完成,这就是一种最简单的服务组合和编排,你可以看到在你复杂业务逻辑实现过程中基本都是调用的各个业务服务,数据服务,技术服务来组合完成的,在这种模式下虽然没有可视化的BPEL服务编排,但是已经体现了通过服务组合来实现业务的思想。
服务本身无状态,因此很难通过调用多个服务来控制事务,因此对于组合服务的实现尽量下移到领域服务层来完成,在领域服务层通过类似spring事务处理机制来控制事务。或者说组合服务不是去调用原子服务,而是直接调用底层的API进行组合,以避免太多的分布式事务处理。服务本身粗粒度,在服务中传递的对象更加强调是一个完整的业务对象,完全业务对象具有完整的事务属性和生命周期,引出也方便应用对于完整的业务对象进行完整的事务控制。
最后,一个业务系统内部可以选择实现一个最简单的服务总线,也叫做系统内部轻量ESB。实现这个目的并不是为了UDDI统一的服务目录库。而是业务系统本身服务化后,组件之间会出现大量的服务消费和调用,一个业务系统需要对这些业务访问调用进行统一的管控,包括服务运行监控,安全和鉴权,统一服务地址等。这些是基本的需求。
当然没有真正意义上的服务总线也不要紧,一个业务系统服务化后,在一种标准的模块化服务架构下,是很容易的实施和接入到一个ESB上面的。这个并不是基于SOA架构的业务系统的重点。包括现在的OSGI框架,也并不是完全的符合轻量ESB总线的要求。而对业务系统引入了更多在实现上的复杂性。
以上是最基本的要求和原则,最难的还是在如何划分业务组件,如何抽象粗粒度和可复用的服务。
前面已经有很多文章谈到过,SOA思想的核心根据定义可以拆分为两个重要的内容,一个是根据业务建模和架构设计过程找寻到粗粒度的可重用的服务;其二是这些服务可以组合,可以组装和编排以满意业务流程的需求。前者重点对应的是ESB服务总线,而后者重点对应的BPM和BPEL相关业务能力。
对于一个基于SOA的架构的业务系统,应该符合以下这些最基本的特征:
首先是业务系统是组件化和模块化的,需要在业务系统构建过程中体现CBM和业务组件化,组件能力化的思想。一个完整的业务系统通过业务建模和架构分析应该根据松耦合的原则拆分为多个业务组件,业务组件最终转换为应用系统实现中的应用模块(服务组件+技术组件)。每一个组件都相对独立,都可以独立进行分析设计,开发,测试,部署和后续运维的管理。
在应用开发中,我们经常可以看到一个业务系统划分为多个模块,但是各个模块之间仍然是完全混乱的交叉调用,不符合松耦合的思想。也完全约束了各个组件可以完全独立部署和管理。同时虽然有时候进行了组件的划分,但是数据库没有完全拆分开,应用层和逻辑层划分了组件做了拆分,但是到了数据库又完全混在了一起,也导致组件模块之间无法拆离。
组件划分的粒度,组件应该内聚的功能需要仔细分析,这些是组件之间能够松耦合的基础。组件之间的交互或者说组件向外暴露的能力只能以服务的方式进行,这个服务需要满足粗粒度服务的基本特征。即对于服务的消费方完全不需要了解组件内部的实现逻辑和细节,而只需要根据业务场景调用组件朝外暴露的能力。
组件以暴露粗粒度服务为原则,能够使用组合服务的就尽量使用组合服务,不能使用组合服务的时候才使用更下层的业务和数据的原子服务。这些服务构成一个组件核心的领域层。但是要注意的是不是领域层所有的服务都需要朝外部暴露,而仅仅是涉及到跨组件交互的服务才需要朝外部暴露。在这里还要注意的就是暴露的服务是领域层的能力,而不是数据库级别的CRUD,我们很多时候看到为了减少服务的数量,全部暴露为通道形式的DAL类服务,这本身是完全违背原则的。
服务本身就是轻量的API,因此服务具体实现是采用soap webservice还rest或其它方式并不重要,重要的是服务接口和契约只要不变更,即对于消费该服务的模块就不应该造成各种重新编译或部署的影响,这些轻量API或服务需要达到的一个基本的要求。
其次,服务本身需要是可复用的,服务的目的不仅仅是为了解决组件间的交互,这仅仅达到了服务能够松耦合各个组件的目的。而为了满足服务的可复用性,即需要考虑在各个业务模块的基础上,应该有一个更加底层的提供共性能力的基础公共模块,这个模块提供共享的可复用的服务能力出来。
前面曾经谈到过对于业务系统一般分为两个大的类型,一个是数据驱动型的,一个是流程工单驱动型的。对于资产管理,资源管理属于前置;对于OA,ITIL类业务系统完全属于后者。而对于前者往往都有一个核心的底层共享数据模型,这个共享数据模块上层的业务模块都需要用到。这个底层则提供共享的可复用的能力。即使对于流程驱动的应用,往往也存在架构分析设计中识别出可复用的内容进行提取。
对于安全,消息,缓存,文件,日志,异常,4A,流程引擎等技术类组件,更加是所有模块都需要复用的内容,在一个业务系统中的设计中这些需要抽取为独立的技术组件,提供可共享的技术服务。如果在实现过程中再结合AOP的思想将更好,这样业务系统构建和实现过程中将更加简单。
再次,业务流程的实现或复杂业务逻辑的实现应该体现服务组装或服务编排的思想。在这里和是否使用BPM工具,使用BPEL没有太必然的关系。在这里不是指的工作流引擎自动处理的审批流,而更多的是指需要程序自动化处理的业务流或复杂业务规则。如资产调拨可能需要调用多个原子服务来完成,这就是一种最简单的服务组合和编排,你可以看到在你复杂业务逻辑实现过程中基本都是调用的各个业务服务,数据服务,技术服务来组合完成的,在这种模式下虽然没有可视化的BPEL服务编排,但是已经体现了通过服务组合来实现业务的思想。
服务本身无状态,因此很难通过调用多个服务来控制事务,因此对于组合服务的实现尽量下移到领域服务层来完成,在领域服务层通过类似spring事务处理机制来控制事务。或者说组合服务不是去调用原子服务,而是直接调用底层的API进行组合,以避免太多的分布式事务处理。服务本身粗粒度,在服务中传递的对象更加强调是一个完整的业务对象,完全业务对象具有完整的事务属性和生命周期,引出也方便应用对于完整的业务对象进行完整的事务控制。
最后,一个业务系统内部可以选择实现一个最简单的服务总线,也叫做系统内部轻量ESB。实现这个目的并不是为了UDDI统一的服务目录库。而是业务系统本身服务化后,组件之间会出现大量的服务消费和调用,一个业务系统需要对这些业务访问调用进行统一的管控,包括服务运行监控,安全和鉴权,统一服务地址等。这些是基本的需求。
当然没有真正意义上的服务总线也不要紧,一个业务系统服务化后,在一种标准的模块化服务架构下,是很容易的实施和接入到一个ESB上面的。这个并不是基于SOA架构的业务系统的重点。包括现在的OSGI框架,也并不是完全的符合轻量ESB总线的要求。而对业务系统引入了更多在实现上的复杂性。
以上是最基本的要求和原则,最难的还是在如何划分业务组件,如何抽象粗粒度和可复用的服务。