技术开发 频道

详解SOA五种基本架构模式

模式一:服务托管

    服务托管是我们要讨论的第一个模式。它是最基本的模式,或者至少是最基本的模式之一。服务托管模式主要负责运行着服务实例的环境,以及与此相关的路由任务。

    问题

    随便选一个服务,任何服务都可以,别告诉我具体是哪个:)。你可以找到一些处理传入的消息或请求的监听代码;你可以找到一些连接组件的代码,还有一些初始化并激活这个服务的代码;或许你还能找到一些能适当地配置服务的代码。有没有觉得我很厉害?实际上,你可以在服务里找到上面的所有代码,至少是大部分。

    有许多工作都是重复性的、常见的。我们可以好好利用这一点。

    如何使服务能够适应不同的配置,避免设置监听器、组件连接等重复性常规工作?

    第一个办法(实际上也不是什么办法),就是为每一个服务重写所有的连接代码。很显然,这不是个好方法,因为重写的次数越多,就越可能产生一些缺陷。并且,对于维护来说,许多重复的代码产生的问题更为严重。在维护的时候,你不仅要确保每一个服务中的缺陷都已经得到修正,还要保证没有任何疏漏、所有的服务都已经同步更新。

    另一个相对较合理的办法,就是创建一个共同任务库,所有的服务都通过API与库相连接。这样确实会有所帮助,但是为了充分利用库的功能,你仍然需要编写连接代码。

    还有一个办法是利用继承创建一个超类,用超类实现共同的功能,然后让各个服务继承这个类。然而利用继承也有问题,因为服务的功能通常无法通过一个单独的类获得很好的实现。此外,不同的服务所处理的业务也完全不同——否则它们就是一样的服务了。因此,也无法让把这些服务归于同一类结构。

    继承几乎已经可以解决我们面临的问题——因为我们只需要写一次代码,只有不同的服务才需要定制。如果想不用继承得到相同的结果,我们就得使用框架。

    解决方案

    创建一个通用的服务托管组件,把它当作服务的容器或者框架。容器是可以配置的,并执行服务连接、安装等工作(见图2)。

    

    服务托管就像是一个肩负着许多职责的迷你框架。它的第一个职责就是正确地示例服务所包含的组件或类。服务托管还负责读取配置信息,比如,它可以读取服务消费者用来连接服务的端口。其它职责包括创建服务环境,比如在终端创建监听器。最后,服务托管可以负责连接组件——终端监听器上的协议绑定或者创建一个与数据库的连接。所有这些职责的共同特征是它们都与服务的实例化和初始化有关,并且正如我们在问题部分所描述的一样,你很可能会在多个服务中遇到同样的情况。前面已经提到,服务托管是一个框架,与第二种方法中描述的库的概念有所不同。库是一个实用类或方法集,你可以调用它们来获取特定的功能。而框架则包含了一些功能或流程,并通过调用代码来扩展流程或将其转变为具体的流程。这就是“控制反转(Inversion of Control)”原理。这种原理已经在面向对象的框架中获得广泛的应用,比如Spring或Spring.NET、Picocontainers等。

    服务托管模式与其它方法相比有许多优势。其中一个优势前面已经提到——即服务托管是一种框架,它可以调用代码来改善性能,而无需你亲自进行编排。另一个优势是它能更好地实现开放/封闭原则(OCP)。OCP原则认为类应该是可以扩展的,但是不能修改;而框架的概念正是这个原则的具体表现。

    一个服务托管可以托管多个服务——虽然这种情况可能并不常见。我们曾经构建了一个系统,使用的方案规模小到一台计算机即可应付。这真的很方便。如果换另一种方案,那么服务可能就要扩展到多台计算机上,这样你就得应用多个服务托管实例,各个主机托管服务的一部分,而不是整个服务。

    服务托管模式已得到了技术供应商的广泛应用,这一点我们可以在下面的技术相关部分看到。

    技术相关

    这一部分我们将简单地了解一下利用当前的技术实现这个模式的意义。

    服务托管是一种基本的SOA架构模式,因此大部分技术都支持这种模式。JAX-WS和Windows Communication Foundation都能用标记语言(XML)进行配置,并使用Web服务器(比如Servlet引擎或IIS)完成大部分的连接工作。

    Windows Communication Foundation还提供了一个称为ServiceHost的类。Microsoft的说明文档是这样解释ServiceHost的:“如果你不使用Internet Information Services (IIS)Windows Activation Services (WAS)提供服务,就用ServiceHost类来配置并提供服务。IIS和WAS都能与ServiceHost进行交互。”从根本上说,其内置WCF对ServiceHost的执行与我们所描述的服务托管模式是基本一致的。

    如果你要自己实现一个服务托管模式,那么你可以从Spring(或者Spring.NET)、Picocontainers等轻量级容器中学习如何进行连接和实例化。这方面的技术实现并不多,因为服务托管模式实际上是一种相对简单的模式。

    轻量级容器与依赖性注射

    Spring和其它一些框架被称为“轻量级容器”。这些“轻量级容器”的优点是它们提高了方案的松耦合性和可测试性。这种优点是通过一种非SOA模式——依赖性注射模式(Dependency Injection Pattern)实现的。依赖性注射,正如名字所示,指一个类通过第三方“汇编程序”提供所需的接口。通过依赖性注射技术,类不再依赖于特殊的实现,而只依赖于接口和抽象类。这使可测试性获得了提高,因为你可以使用桩或模拟来为类提供虚拟环境。这同时也提高了灵活性,因为只要它们之间的关系不变,你就可以轻松地改变具体的实现方式。

    服务托管模式是一种简单而有效、并且已经获得广泛应用的的模式。

    质量属性场景

    这一部分是从需求的角度讨论使用模式的架构效益。大多架构需求是根据使用场景表现的质量属性(可扩展性、灵活性、性能等)来描述的。这些场景也可供其它可以应用模式的情况参考。

    使用服务托管模式的主要原因是重用性。由于多个服务需要使用的相同任务只需写一遍代码,因此重用性也随之提高。这还能带来另一个好处,就是可靠性的提高,因为你只需要调试一次。另外,服务托管模式还能提供可移植性的质量属性。由于这个模式的分离问题的效应,因此可移植性也得到了增强。另外由于可以使用标记语言配置服务环境,可移植性又会得到进一步提高。

    下面的表2列出了几个场景,可以给你虑使用服务托管模式的理由。

质量属性(第一层)质量属性(第二层)场景示例
重用性减少开发时间开发时,在20分钟内设定新服务的环境。
可移植性安装系统必须支持以服务为单位对服务器进行配置。安装过程中,从一个环境切换到另一个环境所用时间应该少于一小时。

     一旦配置好并开始运行服务,你就得决定服务应该是被动式的(应请求唤醒)或是主动式的(无需等待服务消费者激活,并做一些零工,比如显示状态或处理超时)。正如名字所示,主动式服务模式下,服务是主动运行的,而不是被动的。

1
相关文章