读书人

ESB之旅(loanBroker续四)

发布时间: 2012-11-17 11:14:15 作者: rapoo

ESB之旅(loanBroker续4)

? 前面3篇基本都围绕在loanBroker例子的背景和外围知识上了,只有上篇开头说明了如何改造loanBroker使得可以在eclipse内部启动调试,花费时间学了背景知识不是浪费时间,磨刀不误砍柴工,对例子的了解加深了许多。下面在改造的配置文件基础上详细分析loanBroker。从上到下逐条分析配置文件的配置项:

? 1、

? 这是个自定义转换器、没啥说的、想看转换器咋写自己去看,下次要用转换就复制黏贴、改巴改巴、o了。这个转换器把rest字符串形式的请求消息转为对象形式的消息:CustomerQuoteRequest(包含Customer)

? 3、

? 这是两个被原来的ejb所引用的转换器,因为外部CA服务的方法参数与mule的接口CreditAgencyService不符,但在使用了DefaultCreditAgency以后就不存在方法参数不符问题了,所以这两个转换器也都用不到了已经。不过CreditProfileXmlToCreditProfile是个更复杂的转换器也可以结合原有EJB来看看,它的作用是用dom4j的xpath提取功能从EJB返回的xml文档中提取出customer-history客户信用记录和credit-score信用积分。

? 第二个expression-transformer表达式转换器:在当前消息上执行数个表达式...返回对每个表达式求值后的结果对象数组,它的子元素只有一个:return-argument(一个表达式),上面的配置望文生义,就是指计算对象(evaluator)是个pojo bean、表达式就可以直接写这个pojo的属性名,相当于调用getName、getSsn方法,作用是在向EJB请求之前提取出客户的name和ssn作为请求ejb的参数。

4、

? 这是个消息属性转换器,贷方网关服务 引用了它来增加消息属性。消息属性转换器可以为一条消息增加修改删除属性(这应该是JMS的一种机制就是在JMS容器内的消息可以随意附加额外属性,有点像邮件附件。这里应该是mule借鉴了JMS提供了类似机制)。这里是使用groovy表达式 遍历LoanBrokerQuoteRequest(payloaders)对象的Bank[] lenders、把每一个Bank对象的String endpoint这个属性拿出来、组合成一个以recipients为键的消息属性。

?

? 另外强调一下:经测试发现recipients这个key值不是随便乱写的,在mule中以“recipients”作为消息属性键值就指定了这个消息属性一定是接收者列表而且在随后的消息处理流程当中凡是使用了接收者列表路由如<static-recipient-list-router>的地方一定会首先找key值为recipients的消息属性(array或list)并作为接收者集合来遍历、逐个发送消息,我觉得这就是所谓的routing-slip行为——默认路由、 意思是不必再配置繁杂冗长的具体路由端点了。这就是为什么 银行网关服务 把消息路由到各个银行的配置如此简洁的原因:贷方网关服务 首先引用SetLendersAsRecipients消息属性转换器来增加消息属性、然后把消息发送到 银行网关服务、银行网关服务 只是个中转站(没有component)、它拿到消息后需要转发各家银行,但是它的出站路由配置异常简洁:

就这么一句话,甚至连这句话都可以不用,因为这只是个过滤器验证一下recipients不能为空、经测试完全可以去掉、也就是写为:

? 对于其他过滤器、路由器、转换器以及属性,你可以像这样添加表达式:#[<evaluator>:<expression>]?

? 如下表达式将消息头中的ID加入消息属性,用的是XPath表达式:

? 对象要走JMS消息通道之前得经过转换,mule提供了默认转换器。还可以参考:mule源码学习

? 6、

? 这两个端点都是<service name="LoanBroker">贷款中介服务 的入站端点,也就是都是消息流的起点,第一个是用来接收客户请求的jetty rest服务、第二个是接收来自控制台输入的客户请求——但它并不是stdio,我们上回提过要从控制台输入的话得以java application方式运行LoanBrokerApp、参见其main方法的:

? loanBrokerApp.run -> AbstractLoanBrokerApp.run -> 我们都是选择1 -> 进入AbstractLoanBrokerApp.request方法注意到里面的这行代码:

? 第一个端点消息进入后需要经过转换转换为CustomerQuoteRequest类型、第二个端点client发送的就是CustomerQuoteRequest类型所以无需转换。

?

7、

? 第一个端点没用(因为无处引用并且注释掉后无影响)

? 第三个端点:贷款中介服务 -> CreditAgencyGateway -> <service name="CreditAgencyGatewayService">征信所网关服务

? 第二个很重要,是<service name="BankingGatewayService">银行网关服务 的出站:

?以及贷款中介服务 的异步应答器的入站:

? 我们说过异步应答器的重要性,在这里结合reply-to再说一下,异步应答器在配置上属于service的一部分,本来按照SEDA一个service就是一个stage,但是个人认为异步应答器在运行时是作为新线程启动运行的,这也是“异步”的含义,service的component运行结束之前会启动新线程运行异步应答器然后自身就结束了,异步应答器还持有着service的入站端点(聚合处理消息完后发回给入站端点返回客户),它运行起来以后会在它自己的入站端点上起一个监听,监听收集从远方回来的消息应答。一个reply-to配置端点一定对应着一个async-reply异步应答路由器的入站端点,<reply-to>配置端点一定是在下一个service起作用的、比如说service1分发消息到service2,service1的出站路由配置了reply-to端点,那么service2处理完消息后将会把结果发往reply-to端点。

? 任何outbound router出站路由都可以有一个reply-to endpoint(应答到端点)指定消息在接收者处理完之后的路由去向 ,比如本例的<service name="BankingGatewayService">银行网关服务 的出站路由:

? reply-to端点可以是任何合法的mule端点,但是需要传输器的支持,关于哪些传输器支持reply-to请参考mule支持的传输器特性列表。

? static-recipient-list-router静态接收者列表路由配置元素上面讲过、这里再罗嗦一点、它和expression-recipient-list-router都属于recipient list routers接收者列表路由器 ,接收者列表路由器 (可能也是EIP的一种)可用于配置通过单个端点向多个端点发送同一条消息,或者当根据消息内容智能路由 (下面有提到,这里又分两种:from message properties or the payload.) 时实现routing-slip行为 。mule自身提供了一个抽象接收者列表实现:org.mule.routing.outbound.AbstractRecipientList,它是一个线程安全的实现基类。静态接收者列表路由带有一个端点的配置列表,这个列表附加在当前消息上or from a statically declared list on the endpoint.(或者附加在一个端点的静态声明列表上)。这个玩意如下配置:

?

9、

?? 第一个端点:<service name="CreditAgencyGatewayService">征信所网关服务 -> LenderGateway -> <service name="LenderGatewayService">贷方网关服务 ,是连接这两个服务的jms端点,官网上例子结构图的jms部分都画在一起了是一条总线,不过这里感觉和vm一样都是点对点的而且是有数条管道。

? 第二个端点:贷方网关服务 -> LenderService -> <service name="LenderServiceService">贷方服务

? 第三个端点:贷方网关服务 -> BankingGateway -> <service name="BankingGatewayService">银行网关服务

? 在这里贷方网关服务的出站路由使用了chaining-router链式路由 来将两个出口端点顺序执行:

?? 也就是贷方网关服务先将消息交给 贷方服务, 贷方服务根据贷款额多少将下一步路由到的银行注入消息之中(此时消息自身就含有了下一步路由到哪里去的信息,参见org.mule.example.loanbroker.lender.DefaultLender类,这就是所谓根据消息内容的智能路由 了吧)。消息体LoanBrokerQuoteRequest的Bank[] lenders属性即被注入了下一步的去向银行。

? ok、让我们连成一线!:

?

? 客户通过浏览器发出请求 -> CustomerRequestsREST? -> 贷款中介服务(同时在 replyLoanQuotes 端点 上 启动异步应答器) -> CreditAgencyGateway -> CreditAgencyGatewayService征信所网关服务 -> LenderGateway -> LenderGatewayService贷方网关服务 -> LenderService -> LenderServiceService贷方服务 -> 银行网关服务 -> 各个银行... -> 银行网关服务 -> reply-to应答到: replyLoanQuotes端点 -> 贷款中介服务的异步应答器(聚合整理响应消息)-> 贷款中介服务的inbound入站端点 -> 客户浏览器

?

? 除了LenderService是vm其他全是jms消息通道、replyLoanQuotes端点是 贷款中介服务异步应答器的入站端点、是整个回路的最后一环。这个例子中异步应答器及其子元素异步应答路由器是关键点之一,再来复习一下users-guid:

? 异步应答器用于异步请求响应场景下的响应接收,在该场景中你必须聚合整理来自远程端点的响应消息,接着返回给当前service的inbound入站端点、然后才能最终返回给用户。典型例子就是发了请求以后启动多个任务并行处理这个请求,每个任务必须都执行完毕以后再汇总聚合整理所有响应然后返回给客户。异步应答路由用于请求响应调用的分支处理、事实上你只能使用异步应答路由+同步调用service(因为异步的消息调用没有响应),mule提供聚合路由器结合消息裂解器或接收者列表路由模式来聚合消息。典型配置:

<async-reply>    <jms:inbound-endpoint queue="bank.quotes"/>    <custom-async-reply-router class="org.mule.samples.loanbroker.routers.BankQuotesResponseAggregatr"/></async-reply>

?

?

10、五家银行使用端点的配置,只是不明白为什么一家银行会配两个端点,比如第一家银行会配Bank1和Bank1In两个端点,两个端点地址有什么关系关联?...

?

? 再往下就是几个service的配置了,service相当于点、endpoint相当于线,我们已经分析清楚了线以及如何用线连接各个点、loanBroker例子实际上已经基本分析完了。

读书人网 >软件架构设计

热点推荐