`
nlslzf
  • 浏览: 1048918 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用Mule ESB与Groovy编排RESTful服务

阅读更多
http://www.infoq.com/cn/articles/restful-services-mule
在过去几年中,REST风格的软件架构获得了越来越多的认可,这主要是因为它减少了系统对动件的需求、同时使系统耦合性更低,弹性更好。
目前越来越多的REST资源出现在企业应用中,因此对这些资源进行编排就显得非常重要了。比方说,典型的业务活动就包含了资源的创建,然后是资源的查找及其他资源的创建等。

本质上来说,与RESTful服务的交互是相当简单的:需要构造并发送适当的请求(请求头和请求体),然后分析返回的响应(响应头和响应体)。完成这个处 理并不需要什么特别的工具或是框架,只要有一个好用的HTTP客户端程序库就足够了。除此之外,由于RESTful交互过程中所涉及到的不同实体是由所谓 的微格式定义的,因此能够轻松解析或是输出这些实体的能力就显得非常重要了。

编排与多个资源的交互是个棘手的问题。我们需要定义编排、处理错误并不断尝试,同时系统必须能够在压力下表现良好。作为一个集成框架,Mule提供了我们所需的一切。

来考虑一个例子吧,某商业系统对新订单的处理需要如下编排:

通过向服务发送一个XML实体来创建一个新订单。
寻找新创建的订单资源并从中提取出确认信息。
根据确认信息并通过邮件网关向客户发送一条确认消息。
我们将在本文详细分析上面每一步的交互过程,同时还会介绍为了获得上述交互所需的Mule动件和Groovy特性。

总体的编排包含了一系列通过特定路由、过滤器以及内存消息队列(aka VM队列)连接起来的Mule服务。 最近InfoQ上的这篇文章介绍了Mule中的消息路由,大家不妨移步一观。

Mule对REST的支持
Mule提供了一种简单而又强大的方式与RESfFul服务交互,那就是Mule RESTPack。

Mule RESTPack提供了一整套连接器与完整的指南以帮助用户创建新的RESTful应用。在本文撰写之际,该软件包提供了三种传送器,分别基于三种流行的REST框架:Abdera、Jersey及Restlet。这样我们就可以轻松公开新的资源,但如何集成现有的REST资源呢?

好消息是Mule标准的脚本模块所提供的Groovy支持有助于Mule HTTP传送器的使用,这样我们就可以成功与RESTful服务交互了。
向Mule发送POST请求
首先来看看第一个交互。HTTP向特定的资源发送一个XML实体来创建订单,如以下程序片段所示:

POST /orders HTTP 1.1
...
<order xmlns='urn:acme:order:3:1'>
   <customerId>123456</customerId>
   <productId>P987C</productId>
   <quantity>2</quantity>
</order>

如果成功服务器的响应如下:

201 Created
Location: http://acme.com/order/O13579
...
<order id='O13579' />
在Mule中,我们可以通过一个简单的HTTP输出端点(outbound endpoint)实现该交互。注意到交互本身是通过向订单创建服务发送一个包含请求值(客户与产品ID、数量)的映射而触发的。该服务如下所示:

<service name="OrderCreationService"> 
  <inbound> 
    <inbound-endpoint ref="OrderCreationQueue" /> 
  </inbound> 
  <outbound> 
    <chaining-router> 
        <http:outbound-endpoint synchronous="true" 
              responseTimeout="15" method="POST" 
              host="${acme.order.hostname}" 
              port="${acme.order.port}" path="orders" 
              user="${acme.order.username}" 
              password="${acme.order.password}" 
              contentType="application/vnd.acme+xml" encoding="UTF-8"> 
              <transformers> 
                <transformer ref="OrderMapToMicroformat" /> 
              </transformers> 
              <response-transformers> 
                  <message-properties-transformer> 
                        <add-message-property key="OrderPlaced" 
                            value="#[groovy:message.getStringProperty('http.status','ERR')=='201']" /> 
                        <add-message-property 
                            key="OrderResourceLocation" 
                            value="#[groovy:message.getStringProperty('Location','')]" /> 
                  </message-properties-transformer> 
                  <object-to-string-transformer /> 
              </response-transformers> 
         </http:outbound-endpoint> 
         <outbound-endpoint ref="OrderCreationResultQueue" /> 
   </chaining-router>     
  </outbound> 
</service>

这全是XML,我们来仔细分析一下:

名为OrderCreationQueue的管道(可以是VM队列或是JMS队列)接收消息。
接收到的消息被直接传递到另一个路由,该路由会将HTTP POST的结果发送到下一个服务,该服务通过名为OrderCreationResultQueue(异步的VM队列)的管道对调用结果进行分析。
通过标准的输出端点在Groovy转换器上执行该HTTP POST请求:
请求订单的微格式是通过一个特定的传送器创建的,下一节将对其进行详细介绍。
通过一小段脚本将结果代码抽取出来并与期望值进行比对。进行比较的目的在于将后面的服务与纯的HTTP隔离开来:我们所创建的boolean类型的属性OrderPlaced是独立的,其名称与进行的编排密切相关。
类似的,在更具上下文含义的OrderResourceLocation名字下复制Location头。注意,该头 有可能丢失(在失败的情况下),在这种情况下,我们将其值默认设为空字符串以避免将null属性加到消息中。
我们使用了一个对象——字符串转换器来“分离”HTTP响应(以流的形式返回)。多亏有了这个转换器,流得到了完全的处理,其内容也通过使用与 HTTP交换相关的编码转换为字符串。当流关闭时,HTTP连接得到了释放;我们不想一直开着它,等待后面的服务从 OrderCreationResultQueue中拿出响应消息。
Groovy MarkupBuilder的好处

OrderMapToMicroformat转换器完成了服务中的重头戏,而它是由Groovy的MarkupBuilder实现的。MarkupBuilder API提供了一种自然的方式生成兼容于特定微格式的XML实体:

<scripting:transformer name="OrderMapToMicroformat"> 
   <scripting:script engine="groovy"> <![CDATA[ 
        def writer = new StringWriter() 
        def xml = new groovy.xml.MarkupBuilder(writer) 
        xml.order(xmlns: 'urn:acme:order:3:1') { 
          customerId(payload.clientId) 
          productId(payload.productCode) 
          quantity(payload.quantity) 
        } 
        result = writer.toString() ]]> 
    </scripting:script> 
</scripting:transformer>

注意map payload中的值是如何用于组装XML元素的:这里解决了一些不匹配的命名约定(比如将clientId转换为customerId)。

如你所期望的那样,该转换器产生了如下输入:

<order xmlns='urn:acme:order:3:1'> 
   <customerId>123456</customerId> 
   <productId>P987C</productId> 
   <quantity>2</quantity> 
</order> 

除了正确的内容类型外都是订单的RESTful服务用于创建新资源所需的内容。

分析

现在我们来看一下负责异步分析订单创建结果并决定是否需要进一步进行编排的服务:

<service name="OrderCreationResultProcessor"> 
  <inbound> 
    <inbound-endpoint ref="OrderCreationResultQueue" /> 
     <selective-consumer-router> 
        <message-property-filter pattern="OrderPlaced=true" /> 
     </selective-consumer-router> 
     <logging-catch-all-strategy /> 
  </inbound> 
  <outbound> 
    <pass-through-router> 
      <outbound-endpoint ref="SuccessfulOrderQueue" /> 
    </pass-through-router> 
  </outbound> 
</service> 

我们使用的选择性消费者(selective consumer)所接收的消息中一定要包含订单成功处理的头信息。如果该头信息为true,那就通过一个名为SuccessfulOrderQueue 的内存队列将该消息路由给第三个(也是最终的)服务,该服务会处理订单成功创建的消息。注意在这个例子中我们只是简单地将错误消息以日志的方式记录下来, 但在实际应用中需要将错误消息发送给专门的队列以进行后续的分析或是及时的反馈。

向Mule发送GET请求
组成该编排的最后一个服务负责HTTP GET处理,它会获得新创建的订单,订单中包含了额外的值以形成一个合法的消息供email网关使用。如下是个示例交互:

GET /order/O13579 HTTP 1.1
200 OK
Content-Type: application/vnd.acme+xml
...
<order xmlns='urn:acme:order:3:1'> 
  <customerId>123456</customerId> 
  <productId>P987C</productId> 
  <quantity>2</quantity> 
  <customerEmail>foo@bar.baz</customerEmail> 
  <estimatedShipping>2009-31-12T00:00:00Z</estimatedShipping>
</order>

好消息是Mule的HTTP传送包含了一个名为rest-servicecomponent的组件,该组件简化了服务与REST资源的交互。幸好有了这样一个组件,我们就无需将GET操作的结果发给随后的服务了,相反可以在单独的服务中完成一切。除此以外,它还支持在配置中使用表达式,这样就能实现与动态构建的URL之间的连通了。

<service name="SuccessfulOrderProcessor"> 
<inbound> 
  <inbound-endpoint ref="SuccessfulOrderQueue" /> 
</inbound> 
<http:rest-service-component httpMethod="GET" 
   serviceUrl="#[header:OrderResourceLocation]" /> 
<outbound> 
  <pass-through-router> 
    <outbound-endpoint ref="EmailGatewayQueue"> 
      <transformers> 
       <object-to-string-transformer /> 
       <transformer ref="OrderMicroformatToEmailMap" /> 
      </transformers> 
    </outbound-endpoint> 
  </pass-through-router> 
</outbound> 
</service>

在接收到成功的订单消息后,该服务使用REST服务组件生成一个HTTP GET请求,并将该请求发送给此前存储在OrderResourceLocation属性(aka heade)中的URL。注意到我们是如何通过Mule表达式框架(使用#[...]语法)在组件中注入动态URL的。

在将GET请求的响应发送给负责与email网关进行通信的服务前,我们对XML订单实体进行了两次转换:

如上所述,我们“分离”了响应实体。
使用转换器解析XML实体并构建一个映射以供接下来的服务使用。这一次,又利用到了Groovy的强大功能。
Groovy's XmlSlurper Happiness

Groovy的XmlSlurper是解析XML微格式的理想工具,这要归功于其类似DSL的API。

如下代码展示了OrderMicroformatToEmailMap转换器的实现:

<scripting:transformer name="OrderMicroformatToEmailMap"> 
  <scripting:script engine="groovy"><![CDATA[ 
    def order = new XmlSlurper().parseText(payload)
				.declareNamespace(acme: 'urn:acme:order:3:1') 
    result = [emailId:'OrderConfirmation', 
		emailAddress:order.'acme:customerEmail'.text(), 
		orderId:order.@id.text()] 
   ]]> 
  </scripting:script> 
</scripting:transformer>

没错,就两行Groovy代码,我们使用了一个命名空间感知的XML解析器和一个map构建器。其好处真是让人难以置信,不过这就是创建map(email网关服务所期望的)所需的全部内容。

最终的REST
在本文中,我们遵循着一个事先定义好的编排,新订单资源的URL是唯一的动态元素。开发者可以利用示例中介绍的转换器和表达式来支持更多的动态交互,如果你打算遵从HATEOAS路线,你就能获得一切。如果事实如此,那其他的Mule路由就唾手可得了,比如可以创建幂等接收者的 路由。你也看到了Groovy的强大功能和灵巧性加上Mule的通信能力极大地简化了与RESTful服务的交互。Mule的表达式和少量的Groovy 脚本能够有效地动态定义Mule配置。除此之外,通过使用异步的VM队列将编排的各个步骤链接起来可以在最大负荷下优雅地降级,这要归功于Mule内在的SEDA架构。

借助于这些强大的工具,集成REST资源变得非常简单了。

祝你好运!

大家可以从http://dossot.net/datastore/mule-groovy-rest.tar.gz下载完整的配置和相关的测试资源,这是一个独立的Maven项目。

查看英文原文:Orchestrating RESTful Services With Mule ESB And Groovy。
http://www.infoq.com/articles/restful-services-mule
分享到:
评论

相关推荐

    MuleESB集成webservice+restful(sprintboot+mybatis+mysql)+activeMQ+javamail

    MuleESB集成webservice+restful(sprintboot+mybatis+mysql)+activeMQ+javamail,五天的研究成果,集成了我所关注的点,希望有更多的朋友一起学习进步。

    ESB原理及Mule ESB实践

    - 许多知名公司如沃尔玛、惠普、索尼、德意志银行和花旗银行都在使用MuleESB。 4. **Mule ESB的安装与配置** - MuleESB有两个版本:社区版和企业版。社区版免费,适合初学者和小型项目;企业版提供了更多高级...

    mule -esb 源码

    本文将围绕Mule ESB的源码进行深入探讨,揭示其核心设计理念与工作原理。 首先,`logging.conf`是日志配置文件,它定义了Mule ESB的日志记录行为。在Mule中,日志系统是至关重要的,因为它提供了一种跟踪和调试应用...

    Mule ESB手册-中文版

    这些端点使得Mule ESB能够与不同的系统进行通信。 5. 组件(Components) 组件是Mule ESB流程中的基本构建块,用于执行特定的操作。文档中提到了Java组件、显示组件(EchoComponent)、日志组件(Logger)、REST...

    mule IDE (mule ESB)

    Mule ESB 是一个轻量级的基于java的企业服务总线和集成平台, 使得开发人员可以快速,简单的连接多个... Mule ESB 包含如下强大的能力: 服务创建和托管— 暴露和托管可重用服务, 使用Mule ESB作为一个轻量级服务容器.

    MULE ESB-4.1企业版运行环境

    MULE ESB(Mule Enterprise Service Bus)是Anypoint Platform的核心组件,它是一个强大的、全面集成的企业服务总线(ESB),专为构建、部署和管理API和集成解决方案而设计。MULE ESB-4.1是MuleSoft公司推出的企业版...

    MuleEsb开源框架简介.pdf

    Mule ESB 是一个基于 Java 的轻量级企业服务总线和集成平台,允许开发人员快速便利地连接多个应用,并支持应用间的数据交换。Mule ESB 支持集成现有系统而无论其底层采用何种技术,如 JMS、Web Services、JDBC、...

    mule esb开发手册

    Mule ESB 是一款强大的集成平台,能够连接各种应用程序、数据源和服务,实现企业级的数据集成与服务编排。下面将从配置、服务、消息模式、端点、云连接以及构建块等方面,深入解析 Mule ESB 的核心概念和技术要点。 ...

    MuleESB帮助文档

    "MuleESB3"这个文件名可能指的是Mule ESB的第三个主要版本。在该版本中,用户可以期待更完善的特性和改进。对于初学者,建议首先通过官方文档了解Mule ESB的基本概念和工作原理,然后使用Anypoint Studio实践创建...

    MuleESB3.0中文教程

    ### MuleESB3.0中文教程知识点梳理 #### 一、Mule ESB 3.0概述 - **定位**:Mule ESB 3.0是一款轻量级的消息框架和整合平台,旨在帮助企业轻松地集成不同的系统和服务。 - **核心特性**:基于EIP(Enterprise ...

    MuleESB_3.0_中文教程

    Mule ESB(Enterprise Service Bus,企业服务总线)是一款强大的开源集成平台,专为构建可扩展、灵活和可靠的分布式应用程序而设计。Mule ESB 3.0是该平台的一个重要版本,提供了许多改进和新特性,使得它在处理企业...

    mule esb cookbook 随书源码

    《Mule ESB Cookbook随书源码》是一个与Mule ESB相关的实践指南,它包含了大量实例代码,旨在帮助读者深入理解和应用Mule ESB这一开源企业服务总线(Enterprise Service Bus)。Mule ESB是业界广泛采用的ESB解决方案...

    mule ESB 3 user guider

    描述:本手册旨在为用户提供对Mule ESB 3的基础使用指导,强调了Mule ESB作为一个社区成熟且文档丰富的开源企业服务总线(ESB)的使用方法。 知识点说明: 1. Mule ESB概述: Mule ESB是一个开源的中间件平台,...

    mule esb 的简单介绍

    Mule ESB,全称Mule Enterprise Service Bus,是一个开源的企业服务总线系统,旨在促进不同应用程序和服务之间的数据交换和集成。Mule的核心设计是基于轻量级的Java平台,尤其是J2EE 1.4标准,使得它能够在各种企业...

    mule esb 项目 例子 入门

    Mule ESB(Enterprise Service Bus,企业服务总线)是一款强大的开源集成平台,它帮助企业将不同的系统、应用程序和服务连接在一起,实现数据的高效流转。本教程将带您入门Mule ESB项目,通过实例学习其核心概念和...

    Mule ESB开发工具以及相匹配的英文手册和中文手册(翻译狗充值翻译)

    Mule ESB(Enterprise Service Bus,企业服务总线)是一种开源的集成平台,由Mulesoft公司提供,它主要用于构建和管理API及企业内部系统的集成。Mule ESB的核心特性是轻量级、高性能和易用性,它允许开发者快速地...

    MULE ESB-4.1社区办运行环境

    MULE ESB(Message Broker Enterprise Service Bus)是一款强大的企业级服务总线,由Mulesoft公司开发,它提供了一个集成平台,用于连接各种应用程序和服务,实现数据的高效传输。MULE ESB-4.1社区版是Mulesoft为...

    mule esb mule esb打包手册文档

    Mule ESB(Enterprise Service Bus,企业服务总线)是一种强大的集成平台,它允许不同的系统、应用程序和服务之间进行无缝通信。Mule ESB的核心功能包括数据转换、协议适配、消息路由以及流程管理,旨在简化企业的IT...

Global site tag (gtag.js) - Google Analytics