【发布时间】:2015-05-23 16:32:53
【问题描述】:
我正在转换 Spring 托管编排服务以使用 Spring Integration 作为概念证明。
我已经运行了基本应用程序,但遇到了一个主要瓶颈。
应用程序使用入站网关从标准 MultivaluedMap 获取 XML 有效负载:
<int-http:inbound-gateway id="DSOWebServicePOC" request-channel="httpRequestsChannel"
reply-channel="httpResponsesChannel" path="/orchestrate/do" supported-methods="POST"
payload-expression="#requestParams.getFirst("XML")">
</int-http:inbound-gateway>
然后通过直接通道将其发送到 xpath-splitter,旨在将请求(包含许多类似的子请求)分解为可以处理的每个实际请求。
应用程序的性能比原来的服务慢了大约 6 倍,这是由于方法 org.springframework.xml.xpath.Jaxp13XPathExpressionFactory$Jaxp13XPathExpression.evaluate(Node, QName)
这是因为编译后的 XPath 表达式不是线程安全的,并且 Jaxp13XPathExpression 中的方法有一个同步块 - 结合 Spring 使用单例...在原始服务中,我使用了一个包含编译后的 XPathExressions 的本地线程。
我尝试了自定义范围无济于事,这解释了原因
Custom Spring Scope not working for Message Channel
我已经按照动态 ftp 的示例,但使用线程名称作为映射键。我已经将它与包含传入通道、拆分器和 xpath 表达式的子应用程序上下文相结合,但在代码中,通道解析器从新上下文中按名称获取 bean:
我不能对 XPathExpression 执行此操作,因为 Jaxp13XPathExpression 是具有默认访问修饰符的抽象类中的私有静态类。
如何获得具有不同范围的已编译 XPathExpression - 无论是请求/会话/线程,而不只是创建具有本地线程的服务激活器并且只是不使用框架的 XML 处理中的构建?
更多信息:
路由器:
<int:router input-channel="httpRequestsChannel" ref="channelResolver" method="resolve" />
解决方法:
public MessageChannel resolve() {
String thread = Thread.currentThread().getName();
ChannelResolverIntegrationBeans beans = this.integrationBeans
.get(thread);
if (beans == null) {
beans = createNewThreadIntegrationBeans(thread);
}
return beans.getChannel();
}
ChannelResolverIntegrationBeans 方法 - XPathExpression 是我最后一次尝试让它工作,但它返回
名为 'dsoBatchRequestXPathNs' 的 Bean 必须是 [javax.xml.xpath.XPathExpression] 类型,但实际上是 [org.springframework.xml.xpath.Jaxp13XPathExpressionFactory$Jaxp13XPathExpression] 类型
private synchronized ChannelResolverIntegrationBeans createNewThreadIntegrationBeans(
String thread) {
ChannelResolverIntegrationBeans beans = this.integrationBeans
.get(thread);
if (beans == null) {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] { "/xmlChildHandlerContext.xml" }, this.appContext);
MessageChannel channel = ctx.getBean("fromDynamicRouter",
MessageChannel.class);
EventDrivenConsumer splitter = ctx.getBean("requestSplitter",
EventDrivenConsumer.class);
XPathExpression expression = ctx.getBean("dsoBatchRequestXPathNs",
XPathExpression.class);
beans = new ChannelResolverIntegrationBeans(channel, splitter);
this.integrationBeans.put(thread, beans);
// Will works as the same reference is presented always
this.contexts.put(beans, ctx);
}
return beans;
}
子上下文 bean:
<int:channel id="fromDynamicRouter" />
<int-xml:xpath-splitter id="requestSplitter"
input-channel="fromDynamicRouter" output-channel="xPathSplitterResultsChannel"
xpath-expression-ref="dsoBatchRequestXPathNs">
</int-xml:xpath-splitter>
<int-xml:xpath-expression id="dsoBatchRequestXPathNs"
expression="/dso:DsoRequests/dso:DsoRequest/*" namespace-map="namespaceMap" />
UDPATE
通过检查它们的哈希码,我发现子上下文中的所有 bean 实际上每个通道都不同。所需要的只是创建子上下文并动态路由到传入通道。
但这并没有真正解决性能问题 - 它仍然比原始服务慢两倍。除非我遗漏了什么,否则 Spring Integration 在这方面似乎表现不佳?
【问题讨论】:
标签: java xml spring xpath spring-integration