对于大型分布式Java应用与SOA,我们可以从以下几个方面来分析:

  • 为什么需要SOA
  • SOA是什么
  • eBay的SOA平台
  • 可实现SOA的方法

为什么需要SOA

  第一个现象是系统多元化带来的问题,可采用对共用逻辑的部分进行抽象的方法,形成多个按领域划分的公用业务逻辑系统;第二个现象是系统访问量、数据量上涨后带来的典型问题,可采用拆分系统的方式来解决。在构建了共用业务逻辑系统和拆分系统后,最明显的问题就是系统之间如何交互。为了整个系统的性能、可用性等考虑,统一的交互方式就成为明显的解决方案了,SOA是这种方式的首选。

SOA是什么

  SOA全称是面向服务架构,它强调系统之间以标准的服务方式进行交互,各系统可采用不同的语言、不同的框架来实现、交互则全部通过服务的方式进行。eBay实现了一个SOA平台来支撑其业务的多元化发展,eBay认为SOA最大的好处是提升了业务的可重用性及灵敏度。但是,SOA平台同样会带来很多挑战,比如:

  • 服务多级调用带来的延时:高性能的服务交互、完善的服务调用过程控制
  • 调试/跟踪困难:
  • 更高的安全/检测的要求:拆分后的每个系统都要相应的安全控制与监测
  • 现有应用移植:
  • Qos的支持:每个服务提供者能够支撑的访问量有限,采用流量控制、机器资源分配等
  • 高可用和高度可伸缩
  • 多版本和依赖管理

eBay的SOA平台

eBay根据这些挑战自行实现了一个SOA平台,这个SOA平台包括以下几点:

  • 高性能、可扩展的轻量级框架
  • 对监测、安全控制、流量控制的支持
  • 服务注册和服务仓库
  • 开发工具

对于一个大型应用中的SOA平台,至少应包含以下几点功能:

  • 统一的服务交互方式,并可实现和现有应用的无缝集成
  • 提供调试/跟踪的支持
  • 依赖管理
  • 高性能与高可用

可实现SOA的方法

基于SCA实现SOA平台

  SCA的全称是Service Component Architecture,是实际上的SOA实现方法指导。首先,我们看看SCA标准是如何定义服务的交互的,包括了如何发布服务、如何调用服务以及支持的通信协议和交互方式三个方面。

发布服务

  服务遵循SOA以接口方式对外提供,发布服务首先要求系统本身已经有相应的接口实现。为了减少对系统实现的侵入,通过XML定义Component映射到系统本身的接口实现上,在定义了Component后,即可将Component实现的接口以服务的方式发布。用来发布服务的XML示例文件如下:

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://foo.com" name="HelloWorldComposite">
    <component name="HelloWorldComponent">
        <implementation.java class="DefaultHelloWorld"/>
    </component>
    <service name="HelloWorldService" promote="HelloWorldComponent">
        <interface.java interface="HelloWorld"/>
    </service>
</composite>

这些标签的主要关系如下图所示:

《分布式Java应用之基础与实践》读书笔记三-LMLPHP

component标签主要通过implementation子标签定义和已有系统的集成,SCA提供了对多种实现集成的支持。service子标签用于表明当前component对外提供了什么service,reference子标签用于表明当前component引用了什么service。

调用服务

  调用服务的方式同样可通过简单地定义xml即可实现。用来调用服务的XML示例代码如下:

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://foo.com" name="HelloWorldComposite">
    <component name="HelloWorldComponent">
        <implementation.spring location="beans.xml"/>
        <reference name="HelloWorldService" target="HelloWorldService"/>
    </component>
    <reference name="HelloWorldService" promote="HelloWorldComponent">
        <interface.java interface="HelloWorld"/>
    </reference>
</composite>
// Spring的beans.xml定义如下
<beans>
    <sca:reference name="HelloWorldService" type="HelloWorld"/>
</beans>
支持的通信和交互方式

  SCA标准默认提供的通信方式为SCA、WebService和JMS三种。SCA是指由框架根据运行状况来选择采用相应的通信方式,例如,根据服务端和客户端是否在同一个JVM上,来切换本地调用或者WebService和JMS方式等。WebService的实现为HTTP方式;JMS则可采用多种方式来实现,例如TCP/IP、HTTP等。

  SCA可以在不侵入系统的情况下以多种方式发布和调用服务,并将其注入新需要引用服务的系统中,而且,这些系统同样可以以Java、Spring或C++等多种方式实现。从标准来看,在统一的服务交互方式上,SCA提供了清晰的发布服务、调用服务及无缝和现有应用集成的支持。在调试/跟踪的支持上SCA标准并没有明确的定义,只能自行实现;依赖管理方面也同样没有明确的定义,而且没有定义服务仓库,这给依赖管理的实现带来更大的困难。

基于ESB实现SOA平台

  ESB和SCA不同,它并不是由多个厂家联合制定的SOA实现的标准,可以认为ESB只是个概念,核心思想是基于消息中间件来实现系统间的交互。基于消息中间件所构建的此系统交互的中间场所称为总线,系统间交互的数据格式采用统一的消息格式,由总线完成消息的转化、路由、发送到相应的目标应用,基于ESB构建的系统结构如图所示:

《分布式Java应用之基础与实践》读书笔记三-LMLPHP

通常ESB框架须具备一下5个要素

  • 标准的消息通信格式
  • 消息路由:总线接受消息后,根据消息数据决定需要调用的系统
  • 支持多种的消息交互类型:请求/响应和发布/订阅等方式
  • 支持多种网络协议
  • 支持多种数据格式并能够进行相互转换

  在统一以服务方式进行交互这点上,可以认为ESB中的消息方式交互承担了这一功能,且支持多种通信及交互(同步、异步)方式,在调试/跟踪支持上没有定义,在依赖管理上,由于所有的交互都通过总线来进行,在此基础上可根据消息的流转来判断和形成各个系统的依赖关系。

基于Tuscany实现SOA平台

  在SCA实现框架中,本书选择了Tuscany1.5来分析,这是目前最常用的SCA实现框架之一,下面以一个基于Tuny实现发布服务和调用服务的例子。通过提供一个HelloWorld接口的实现,配置为Spring Bean,并给予Tuscany将其发布为WebService方式的SCA Service。代码如下:

// HelloWorld接口定义
@Remotable
public interface HelloWorld {
    public String sayHello(String name);
}
// HelloWorld接口实现
public class DefaultHelloWorld implements HelloWorld {
    public String sayHello(String name) {
        return "Server response: Hello " + name;
    }
}
// Spring Bean xml的配置如下
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sca="http://www.springframework.org/schema/sca" xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd">
    <sca:service name="HelloWorldService" type="HelloWorld" target="HelloWorldServiceBean"/>
    <bean id="HelloWorldServiceBean" class="DefaultHelloWorld">
    </bean>
</beans>
// 将以上文件保存至resources/spring目录下,命名为beans.xml

// 基于Tuscany将其发布为WebService的配置如下:
<composite name="HelloWorld" targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0" xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:nsl="http://www.osoa.org/xmlns/sca/1.0">
    <service name="HelloWorldService" promote="HelloWorldComponent">
        <interface.java interface="HelloWorld"/>
        <binding.ws uri="http://localhost:8080/services/HelloWorldService"/>
    </service>
    <component name="HelloWorldComponent">
        <implementation.spring.location="resoureces/spring/beans.xml"/>
    </component>
</composite>
// 将以上文件保存至src目录下,命名为publishservice.composite

// 编写一个启动类来完成服务的发布
public static void main(String[] args) throws Exception {
    SCADomain.newInstance("publishservice.composite");
    while(true) {
        Thread.sleep(100000);
    }
}

至此,基于Tuscany的服务发布功能已经完成,关于如何调用服务的代码就不给出了。

  在启动了发布SCA Service的代码后,再启动调用SCA Service的代码,即可在console上看到相应的执行信息,基于以上步骤,很容易在Spring中以WebService的方式发布和调用SCA Servie。以下介绍基于Tuscany如何实现SOA平台。首先还是从统一服务的交互这点分别来看发布服务、调用服务和支持的网络协议及交互方式。

  • 发布服务:在SCA标准的基础上支持更多种实现方式的系统中的功能发布为SCA Service
  • 调用服务:在SCA标准的基础上支持更多种应用集成及调用方式,包括更多语言支持
  • 支持的通信以及交互方式:在SCA标准的基础上支持更多种通信方式

在调试/跟踪方面,当服务器端抛出异常时,会将此异常信息带回到调用端,对于查错而言有一定的帮助;在依赖管理方面、高性能和高可用性方面等,Tuscany没有做专门的处理。

基于Mule实现SOA平台

  Mule是最常用的ESB实现框架之一,首先看看基于Mule如何来实现同样的例示功能。其实,Mule也是通过WebService的方式对外提供HelloWorldService,和Tuscany中不同的地方仅在于配置文件和启动代码两个方面,配置文件中去掉publishservice.composite,改为遵循Mule编写如下配置文件:

<mule>
    <spring:beans>
        <spring:import resource="resources/spring/mulepublisherbeans.xml"/>
    </spring:beans>
    <model name="HelloWorld">
        <service name="HelloWorldService">
            <inbound>
                <axis:inbound-endpoint address="http://localhost:12345/services">
                <soap:http-to-soap-request-transformer/>
                </axis:inbound-endpoint>
            </inbound>
            <component>
                <spring-object bean="HelloWorldBean"/>
            <component>
        </service>
    </model>
</mule>
// 将上面文件保存为publishservice.xml

// 发布服务的启动代码遵循Mule改为如下方式
MuleContext muleContext = new DefaultMuleContextFactory().createMuleContext("publishservice.xml");
muleContext.start();

至此,基于Mule的服务发布功能已经完成,关于如何调用服务的代码也不给出了。

  执行以上代码就实现了以Mule Service的方式调用远端通过Mule Service发布为WebService的功能。我们还是以Mule如何实现SOA平台,看看Mule如何实现服务方式的统一交互。

  • 发布服务:Mule支持以WebService、jms等方式将Spring或普通Java对象昂发布为Mule Service
  • 调用服务:Mule用法较麻烦,原因是ESB强调一切以消息的方式发送给总线
  • 支持的通信和交互方式:支持WebService和jms两种,支持同步和异步方式

在调试/跟踪上,Mule未提供特别的支持;在依赖管理上,Mule所在的MuleSoft提供了一个开源的服务治理框架:MuleGalaxy;在高性能和高可用性上,Mule未优化。

小结

  SCA标准及SCA标准实现的框架对于服务的统一交互支持得很好,ESB及ESB框架则更适用于需要解耦方式的服务交互及复杂的多服务交互的场景,但无论是基于SCA标准、ESB、还是已有的SCA框架和ESB框架,在实现一个大型应用的SOA平台时都还有不少需要自行扩展实现的地方,尤其是在调试/跟踪、依赖管理、高性能及高可用性方面。对于大型应用的服务化,SOA平台是一方面,如何推广实行也是一个重要因素,eBay提及的现有应用移植及培训开发人员是在推广实行时徐亚仔细考虑的。

  以上提及的一个基本的大型应用的SOA平台的特征,而对于一个更加完善的SOA平台,作者认为还需要具备以下几点:

  • 支撑集群环境:软件负载均衡、服务接口或方法级的路由策略等
  • 完善的服务治理:包括依赖管理、状况监测、安全控制等
  • 服务SoS(Quality of Service)的支持
04-15 01:55