使用Mule 2.0基于模式的开发 part2
Submitted by dirksenrademakers on Wed, 2008/05/28 - 2:05am.
Translated by alloyer on Fri,2008/07/31 - 10:00pm.
关键字:ESB Mule Patterns SOA
案例分析:保险经纪人
一个新型的保险公司,EasyInsurance,希望为潜在的客户群提供一个Web服务,这项服务可以从多个你希望得到服务的一类保险公司中得到服务引用。在这个Web站点上线时,只有旅行保险和汽车保险是可用的,但在不久的将来,EasyInsurance公司希望为房产保险提供提供同样的网上服务。
当一个保险请求通过网站进入系统后,将根据保险请求的类型被转发给相应的保险提供方。保险提供方的数量可以很容易地进行扩充。保险提供方的回复将会被显示在网站上,并且可以由保险提供方提供一份保险合同。下图展示了一个该Web 站点的向保险提供方发送请求和回复被发送回站点的功能概况。
在我们的集成解决方案中,还有一问题需要解决,这就是BudgetCar Insurance需要以FTP协议传送的CSV格式的请求,LuxuryCar Insurance需要的是通过JMS发送的XML文件类型的请求,而另一个保险公司ResortTravel Insurance的所有请求都是通过WebService完成的。
基于模式的设计方法
大多数致力于信息集成项目的人应该会熟悉Gregor Hohpe和Bobby Woolf写的企业集成模式(EIP)一书。这本书介绍了许多你可以用以描述和解决你的集成应用,或者编写这类文档的设计模式。下面这部分将向你展示怎样使用EIP一书中阐述的模式来描述这个保险经纪人案例。
首先看下图,它描述了这个案例的请求部分的处理过程。
现在让我们来看一下,这些模式是怎样协同工作来解决保险公司系统的请求部分的消息处理的。我们并不展示出所有的前端用户,只是从EasyInsurance 网站接收到一条保险请求开始。
1. 首先可以看到,网站使用了一个”message endpoint”来将消息发送到一个特定的由代理管理的通道中(这里是一个JMS队列)。
2. 这个队列接下来会被ESB使用JMS的”channel adapter”来读取。
3. 现在消息被ESB路由发到到了内部。第一个路由器是”content based router”,它将分拣消息,并基于请求的类型:汽车或者旅行,将消息路由到下一个组件。
4. 如果消息需要被发送到多个保险公司,这时会使用到接收列表。在消息被真正发送到服务组件前,它首先需要被”transformer”转换成目标消息格式。
5. “transformer”需要保证消息能符合接收者可以处理的格式,所以现在所有剩下要做的就是使用另一个”channel adapter”来发送消息到消息通道,并且这些保险提供方公司可以使用一个”message endpoint”来读取这些消息。
除EIP的使用外,上图的请求消息流展示出了该集成解决方案中不同逻辑边界之间清晰的分离。当然ESB表示的是一种逻辑边界,然而消息代理(JMS Provider)、网站和保险提供方的接入点也被不同的边界分离开了。你可以注意到上图只展示了这个案例中的请求部分。为了设计的整洁和可理解性,最好将请求和应答流画在不同的图中,下图展示的就是应答部分的消息流。
应答消息流的设计图中,大部分的模式已经在前面的图中用过了,只有一个聚合模式是新引入的。聚合用于将BudgetCar和LuxuryCar两家公司的保险回复消息组合成一个回复,使它可以显示到网站上。为了能聚合两家汽车保险公司的回复消息,我们需要一些标识来将回复消息与原始的保险请求消息关联起来。在这个例子中,我们在请求消息中使用了请求ID来建立这种与回复消息的联系。
现在介绍设计阶段的另一个重要步骤:消息设计。因为我们的ESB可以使用Java对象充当消息的有效负载类型,我们将使用基于Java的消息在网站与JMS代理和ESB间进行通信。下页表列出了对保险请求和回复消息的实现。
如表中所示,这个例子中的消息设计非常简单。这个集成解决方案中消息设计的重要部分是CarInsuranceRequest和TravelInsuranceRequest这两种用于内容路由的请求间的区别,还有一个就是用来聚合汽车保险回复的requestID属性。
注意,直到现在我们也没有提到具体的编程工具。在我们的设计中我们仅仅描述什么需要完成。我们现在就可以将设计的集成流和消息将会给开发者或者集成专家,他们可以用具体的技术实现。在这里,我们要自己使用我们的ESB来实现。
- public class CarInsuranceRequest implements Serializable {
- private String requestID;
- private String numberPlate;
- private String carType;
- private int buildYear;
- private boolean companyCar;
- private Date startDate;
- }
- public class TravelInsuranceRequest implements Serializable {
- private String requestID;
- private String destinationCountry;
- private int numberOfPersons;
- private Date startDate;
- private Date endDate;
- }
- public class InsuranceResponse implements Serializable {
- private String requestID;
- private String responseID;
- private String insuranceCompanyName;
- private float price;
- }
保险代理案例的实现:请求部分(待译)
保险代理案例的实现:回复部分(待译)
保险代理案例的实现:总结
现在来总结一下这个案例。对请求部分我们通过JMS接收请求。基于这些接收的消息的有效负载的类型,我们使用基于内容的路由来确定将消息发送到哪里。如果消息是对旅行保险的请求,消息会被发送到旅行保险代理的WebService处。如果请求的是汽车保险,消息则会被发送到汽车保险的公司进行处理。
我们对消息使用了一系列的转换步骤,既使用了ESB内建的转换器,也使用了自己定义的转换器,自已编写的消息转换器来自于汽车保险公司需要的信息与ESB 内部使用的消息格式不相同这一需要。
旅行保险服务的回复被直接返回到网站一直监听着的回复队列中。而汽车保险服务的回复通过它们的requestID进行了聚合,为此我们使用了ESB中标准的集合聚合器和转换器来保证消息有正确的属性。