读书人

ESB之旅(loanBroker续一)

发布时间: 2012-10-11 10:16:10 作者: rapoo

ESB之旅(loanBroker续1)

? 还是mule好,感觉mule像struts、serviceMix像javaFX,在java世界事实标准往往比官方标准更标准。看看sun,“一流的企业卖标准”还得补充点“有时候标准也卖不动”、“有时候一流企业也会被兼并”

? 看了mule 源代码编译指南 。专门了解了一下maven,简略看了一下family168未完成的maven教程 。在loanbroker例子目录下看到pom文件,就装了maven2.2.1(和mule版本号一样),然后执行mvn,果然是下载一大堆依赖、中间死掉2回、删除迟迟下载不完的surefire(maven一个插件)也不成,最后总算完了。名不虚传,仅仅是mvn这么一个例子就费点周章,那要是大规模项目不知道会怎么样。控制台上的最后输出:

[INFO] Surefire report directory: D:\Java\mule-standalone-2.2.1\examples\6loanbroker\bpm\target\sure
fire-reports
-------------------------------------------------------
?T E S T S
-------------------------------------------------------
Running org.mule.example.loanbroker.bpm.JBpmFunctionalTestCase
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.172 sec

Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: D:\Java\mule-standalone-2.2.1\examples\6loanbroker\bpm\target\mule-example-loan
broker-bpm-1.0.jar
[INFO] [install:install {execution: default-install}]
[INFO] Installing D:\Java\mule-standalone-2.2.1\examples\6loanbroker\bpm\target\mule-example-loanbro
ker-bpm-1.0.jar to C:\Documents and Settings\ZDL\.m2\repository\org\mule\examples\mule-example-loanb
roker-bpm\1.0\mule-example-loanbroker-bpm-1.0.jar
[INFO] [dependency:copy {execution: copy-artifact}]
[INFO] Configured Artifact: org.mule.examples:mule-example-loanbroker-bpm:1.0:jar
[INFO] Configured Artifact: org.apache.derby:derby:10.3.1.4:jar
[INFO] Configured Artifact: bsh:bsh:1.3.0:jar
Downloading: http://repository.codehaus.org/bsh/bsh/1.3.0/bsh-1.3.0.jar
[INFO] Unable to find resource 'bsh:bsh:jar:1.3.0' in repository codehaus ......(——codehaus下载不了)
Downloading: http://people.apache.org/repo/m2-incubating-repository/bsh/bsh/1.3.0/bsh-1.3.0.jar
[INFO] Unable to find resource 'bsh:bsh:jar:1.3.0' in repository apache-incubating ......(——apache下载不了)
Downloading: http://download.java.net/maven/1//bsh/jars/bsh-1.3.0.jar
[INFO] Unable to find resource 'bsh:bsh:jar:1.3.0' in repository java.net ......(——sun下载不了)
Downloading: http://repo1.maven.org/maven2/bsh/bsh/1.3.0/bsh-1.3.0.jar
236K downloaded? (bsh-1.3.0.jar)——似乎是从上面仨地方都下不下来最后还是从maven下了bsh(脚本相关)
[INFO] Copying mule-example-loanbroker-bpm-1.0.jar to D:\Java\mule-standalone-2.2.1\lib\user\mule-ex
ample-loanbroker-bpm.jar
[INFO] Copying derby-10.3.1.4.jar to D:\Java\mule-standalone-2.2.1\lib\user\derby-10.3.1.4.jar
[INFO] Copying bsh-1.3.0.jar to D:\Java\mule-standalone-2.2.1\lib\user\bsh-1.3.0.jar

[INFO] ------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------
[INFO] Loan Broker Example ................................... SUCCESS [2.000s]
[INFO] Loan Broker Example: Shared classes ................... SUCCESS [48.203s]
[INFO] Loan Broker Example: Shared classes for unit tests .... SUCCESS [0.094s]
[INFO] Loan Broker Example: Credit Agency EJB ................ SUCCESS [0.250s]
[INFO] Loan Broker ESB Example ............................... SUCCESS [1:02.438s]
[INFO] Loan Broker ESN Example ............................... SUCCESS [1:25.734s]
[INFO] Loan Broker BPM Example ............................... SUCCESS [4:55.625s]
[INFO] ------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------
[INFO] Total time: 8 minutes 14 seconds
[INFO] Finished at: Tue Mar 09 09:57:48 CST 2010
[INFO] Final Memory: 40M/63M
[INFO] ------------------------------------

? 完了,除了SUCCESSFUL也看不出啥有用的信息。

? 按照《Mule2编译指南》svn额外下载了mule、执行命令、很快就BUILD ERROR了,原因是:

[WARNING] Rule 1: org.apache.maven.plugin.enforcer.RequireJavaVersion failed with message: Detected
JDK Version: 1.6.0-4 is not in the allowed range [1.4.2,1.5.0).

? 把JAVA_HOME换成JDK1.5再来、失败、原因是svn命令不识别、估计是《指南》里要求的一个svn东东没装吧。

? 不管了,不搞了。

?

? 继续loanBroker、实际上对loanBroker例子的分析重点在于最后一个例子BPM 。ESB、ESN只是打前站(这些场景可能在后期会有但是现在起步阶段就是要ESB协同使用个工作流而已),阶段性目标是在liferay中使用mule+jBPM 实现业务流程处理、离线消息这些。ajava 上也有些教程。

? 由于ESB例子中的征信所CA(credit agency)使用的是openEJB(不熟),一些ejb相关环境变量和配置文件的问题暂时搞不定,在eclipse中直接运行org.mule.example.loanbroker.esb.LoanBrokerApp时提示:Name "local/CreditAgency" not found,这说明openEJB不是mule启动的,而应该是loanbroker.bat脚本在mule之前单独启动起来的(为了演示mule连接外部服务)。为了实现整个例子在eclipse中联调希望把CA服务改成webService形式,这同时也是一个熟悉的过程,这样的话我们以loan-broker-esb-mule-config.xml配置文件为主,它与loan-broker-esb-mule-config-with-ejb-container.xml的区别在于后者将远程ejb模拟为mule自身的一个EJB Component,表现在后者多配置了一个CreditAgencyService征信所服务模拟EJB :

<!--  This is the CreditAgency Ejb component.  The implementation is the Jndi naming location        of the the Home interface for the CreditAgency bean.  This is just a single inbound endpoint which        with return the result of the invocation        -->        <service name="CreditAgencyService"><!--征信所服务模拟EJB-->            <description>                Much like the previous service the is a gateway/proxy to a LenderService back-end application. In this                instance the LenderService understands our bus message so we just use a chaining router to send the response form                the Lender Service to the next endpoint.            </description>            <inbound>                <inbound-endpoint ref="CreditAgency"/>            </inbound>            <component>                <spring-object bean="creditAgencyEJB"/>            </component>        </service>

?? 征信所服务模拟EJB 引用了creditAgencyEJB组件,这就是被模拟或说被代理的远程EJB组件了,它的配置在配置文件开头,使用jee:remote-slsb来配置,顾名思义这是个远程调用,只是注册到了本地jndi、所以征信所服务模拟EJB配置貌似本地服务组件,实际上它只是远程EJB服务的一个模拟或说代理 。

? 另外征信所服务模拟EJB 还引用了CreditAgency端点作为消息入站的端点:

<endpoint name="CreditAgency" address="vm://credit.agency.service?method=getCreditProfile"/>

?? 注意这是个普通vm端点,那么是谁向征信所服务模拟EJB发消息呢? 是CreditAgencyGatewayService征信所网关服务 ,CreditAgency端点是信所网关服务的 出站端点,所以消息路径是这样的:

??? -> 征信所网关服务 出站 -> CreditAgency 端点 -> 入站 【征信所服务模拟EJB】-> 远程ejb服务 -> 原路返回响应...

? 也就是说征信所网关服务会通过 CreditAgency 端点同步(阻塞方法)调用 征信所服务模拟EJB , 征信所服务模拟EJB 把该客户的信用信息返回,然后 征信所网关服务再带着客户信用信息去调用Lender贷方相关的东东(贷方网关->贷方服务->各个银行、银行评估客户信用返回信贷额度)关于那个vm暂时理解为一个专用消息管道,谁接入这个管道谁就可以通过这个管道互相通讯了,类似jms消息队列吧,activeMQ里有类似概念,更轻量?

? 回过头来看看loan-broker-esb-mule-config.xml,它里面ejb相关的配置有三处:

? 1、ejb:connector的定义(with-ejb-container的配置文件所没有的)

? 2、ejb端点的配置(注意与上述with-ejb-container的配置文件不同):

<ejb:endpoint name="CreditAgency" host="localhost" port="1099" object="local/CreditAgency" method="getCreditProfile" />

??? with-ejb-container的配置中CreditAgency是普通vm端点。这里CreditAgency是一个ejb端点,直接请求远程ejb服务就完了。所以消息路径是这样的:

???? -> 征信所网关服务 出站 -> CreditAgency 端点 -> 远程ejb服务 -> 原路返回响应...

? 中间环节的【 征信所服务模拟EJB 】就没有了,这就是两种配置的区别所在。

? 3、<service name="CreditAgencyGatewayService">征信所网关服务(与with-ejb-container配置一样)的组件配置以ejb端点CreditAgency为消息出站端点:

<component method="getCreditProfile">                    <!-- We invoke the credit Agency service using synchronous which means that a response                    will be returned from the service. there is also a responseTransformer that will                    conver the Xml returned from the CreditAgency Ejb into a CreditProfile object -->                    <outbound-endpoint synchronous="true" transformer-refs="CustomerToCreditProfileArgs"                                   responseTransformer-refs="CreditProfileXmlToCreditProfile" ref="CreditAgency" />                    <!--或者不引用CreditAgency直接配置为:                    <outbound-endpoint address="ejb://localhost:1099/local/CreditAgency?method=getCreditProfile"/>                    如果方法(getCreditProfile)能够携带一至多个输入参数,你把这些参数的类型设定为一个用逗号分隔的列表并使用methodArgumentTypes属性。多重参数做为一个对象数组被传入,成为Mule消息的有效负载。-->                </binding>            </component>

?

? 我的目标就是把这个EJB废掉, 这里的配置中的binding是生面孔,查阅mule-users-guide在component元素的子元素列表中找到了一些binding解释:A binding associates a Mule endpoint with an injected Java interface. This is like using Spring to inject a bean, but instead of calling a method on the bean, a message is sent to an endpoint.

? Bindings: can be configured to bind component interface methods to endpoints. These endpoints are then invoked synchronously when the method is called.——译文:binding把mule端点与一个注入的java接口向关联,就像spring注入bean一样,但是不是调用一个bean方法而是向端点传递一个消息。 binding配置可以把组件接口方法绑定到端点上,当调用接口方法的时刻调用端点。

? 其他的Bindings配置元素定义:

Components can use bindings to call an external service during execution. The bindings used with a Java component bind a Java interface, or single interface method, to an outbound endpoint. The external service to be called should implement the same interface , and the component should encapsulate a reference to that interface, which is initialized during the bootstrap stage by the Mule configuration builder. The reference will be initialized using a reflective proxy class. Binding can be used on Java components and script components.
?? With component bindings, you can configure multiple interfaces or a single interface with an endpoint bound to one or more Mule endpoints. Mule currently supports component bindings for Java components (the default components in Mule) and script components, such as Groovy or JRuby.——译文:组件可以使用bindings在运行时调用外部服务,bindings可以绑定一个接口或单独的接口方法到一个出站端点上,所调用的外部服务应该实现相同的接口,组件应该包含这个接口引用(组件作为javabean将接口引用作为一个普通对象成员并具有getset方法),在启动阶段mule的配置构造器将其初始化:用反射方式将该接口引用初始化为一个代理类。

?

? 使用bindings你就可以配置多个接口或单个带端点接口与一个或多个mule端点相绑定(有点绕口),mule当前支持java组件(默认)和脚本组件(Groovy or JRuby)的绑定。

? 背景标黄的是有点不太理解的地方,因为bindings配置元素的目的是把一个本地接口与一个端点相绑定,端点请求一个外部服务,对外部服务的接口并无要求也要求不了...

? 通过以上解释大概清晰了,我们似乎可以这样总结component组件配置元素的binding绑定子元素的作用:

? ESB的价值在于将原来的点到点(应用到应用)网状消息结构变为点到面(应用到总线),何为面?在上节我们已经讲过面的含义:就是你只管说你要什么、这个面替你包办处理你的要求时所需要的其他依赖 。本例中的依赖 就是客户信用信息,你的要求很简单就是要银行的贷款,但是每家银行要给你放贷还需要依赖 你的信用信息,而这个信息是不可能管你要的,必定是根据你的个人信息向第三方去要,那么这个事情就可以交给bindings去做。这是ESB堪称面而非另一个集中点的关键,有了这个能力的ESB不再是简单的充当消息中转站的消息总线而是服务总线了,否则的话看mule与activeMQ似乎也没区别。那么要与外部服务相通讯势必会遇到外部服务接口与本地接口不匹配,这时就可以使用bindings将本地接口与请求外部服务的端点相绑定,来做接口匹配,这么看这个绑定元素集中体现了ESB的价值,推而广之:“Bindings provide a way to orchestrate flows between services.”使用绑定你就可以在服务之间编排流程了(因为绑定可以在流程中引入其他外部服务、这样你就可以随意在消息处理流程中编排服务的介入了)呵呵,我们歪打正着,本想废掉这个EJB,结果直捣黄龙了。这样的话还可以引申出服务划分的粒度问题...

? 那么运行时bingdings外部服务往往是同步的,也就是需要外部服务在线返回结果的,因为在消息处理流程中请求外部服务往往是需要外部服务提供一些信息来补充消息内容的,所以往往需要synchronous="true",消息处理流程在绑定环节会暂挂等待返回结果,如果网络通讯不畅或远程服务挂掉......这一点需要注意。当然也不一定必须是远程服务,绑定到本地服务也可以,那就没有受制于网络和远程服务之忧了。

? 这个模式非常类似传统RPC远程调用。

? 注意事项:

Note that component bindings will not work with Java Proxy objects, unless the proxy explicitly handles the binding interface method. If using Spring components, ensure that you use CGLib proxies. For more information on the Spring-AOP proxying behavior, see http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-proxying. If you're using the annotation-processors, such as for transactions, you would specify the following:<tx:annotation-driven proxy-target-name="code"><ejb:connector name="ejbConnector" securityPolicy="security.policy" jndiInitialFactory="org.openejb.client.LocalInitialContextFactory"> <jndi-provider-property key="openejb.base" value="${openejb.base}"/> <jndi-provider-property key="openejb.configuration" value="${openejb.configuration}"/> <jndi-provider-property key="logging.conf" value="${logging.conf}"/> <jndi-provider-property key="openejb.nobanner" value="${openejb.nobanner}"/> </ejb:connector>

? 具体配置不管了、我们知道:传输器用于在一个应用程序和另外一个应用程序中间传输消息(实际上就是外部应用和mule之间的通讯)。传输器提供了一系列的、管理指定通道(channel )中消息的方法。例如:Http 传输器用于管理通过Http 协议传输的消息( EJB 传输器用于管理通过RMI协议传输的消息 ,stdio传输器用于管理通过键盘和显示器传输的消息 ) 。传输器的核心是一个连接器(connector), 该连接器维护传输器的配置信息以及状态 , 也就是说配置connector连接器就是在配置transport传输器,上述ejb连接器就配置了如何去连接ejb服务...再往下又配置了一个连接器:

<jms:activemq-connector name="jmsConnector"/>

? 关于这两个连接器、让我们复习一下echo中的连接器,我的配置为:

<stdio:connector name="SystemStreamConnector"        promptMessage="i say: Please enter something: "        messageDelayTime="1000" outputMessage="输出消息="/>

?以此配置运行mule server后console打印:

i say: Please enter something: 1 —— 输入1
INFO? 2010-03-10 17:17:18,812 [EchoUMO.2] org.mule.component.simple.LogComponent:
********************************************************************************
* Message received in service: EchoUMO. Content is: '1'????????????????? *
********************************************************************************
INFO? 2010-03-10 17:17:18,875 [SystemStreamConnector.dispatcher.1] org.mule.transport.stdio.StdioMessageDispatcher: Connected: endpoint.outbound.stdio://system.out
输出消息=1

? 我们看到输入消息以后、SystemStreamConnector.dispatcher.1表示这个连接器启动了消息分发器(第一个线程?)、根据使用的协议选择的分发器为StdioMessageDispatcher、然后StdioMessageDispatcher将消息传递给了system.out就是显示器了。标准流程图:

ESB之旅(loanBroker续一)

? 总结:配置connector连接器也就配置了传输器、根据连接器的协议自动选择消息的接收器和分发器,也就是说配了连接器以后什么传输器接收器分发器这些就都搞定了。连接器的配置有全局性质,因为我们看到连接器配了以后虽然也有名字,但是从没有被引用,也就是说你配stdio标准输入输出连接器那么所有输入输出都会用此连接器、其他亦然。参考mule-2.2.1-getting-started.pdf文档后得知,其实在下面的端点配置当中是可以配置connector-ref的,也就是说可以对一种协议配置多个connector然后以name引用之。

? mule-2.2.1-getting-started.pdf文档和mule-2.2.1-users-guide.pdf文档都是很重要的官方文档,学习mule,这俩文档那是必须的。

?

读书人网 >软件架构设计

热点推荐