Я преобразовываю службу управляемой оркестровки Spring, чтобы использовать Spring Integration в качестве доказательства концепции.
У меня есть основное приложение работает, но столкнулись с основным узким местом.
Приложение использует входящий шлюз для получения полезной нагрузки XML из стандартной MultivaluedMap:
<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, предназначенный для прерывания запроса (который содержит множество подобных подзадач) вниз в каждый фактический запрос, который может быть обработан.
Производительность приложения примерно в 6 раз медленнее, чем исходная услуга, и это связано с методом org.springframework.xml.xpath.Jaxp13XPathExpressionFactory $ Jaxp13XPathExpression.evaluate(Node, QName)
Это связано с тем, что скомпилированные выражения XPath не являются потокобезопасными, а метод в Jaxp13XPathExpression имеет синхронизированный блок - в сочетании с Spring с использованием синглтонов... В исходной службе я использовал локальный поток, содержащий выполненные XPathExressions.
Я пробовал пользовательские области безрезультатно, и это объясняет, почему
Пользовательский весовой диапазон не работает для канала сообщений
Я последовал примеру динамического ftp, но использую имя потока в качестве ключа карты. Я объединил это с контентом дочернего приложения, содержащим входящий канал, разделитель и выражение xpath, но в коде распознаватель канала получает бит по имени из нового контекста:
Я не могу это сделать для 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' должен иметь тип [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;
}
Контейнеры для дочернего контекста:
<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
Я выяснил, что все компоненты в дочернем контексте на самом деле различны для каждого канала, проверяя их хэш-коды. Все, что требовалось, - это создать дочерний контекст и динамически маршрутизировать на входящий канал.
На самом деле это не помогло решить проблемы с производительностью - это примерно вдвое медленнее, чем исходная услуга. Весенняя интеграция просто не кажется успешной в этой области, если я что-то не хватает?
JAXP XPathExpression не является потокобезопасным, но я думаю, вы, вероятно, используете его для доступа к DOM, который также не является потокобезопасным. Рассмотрим переход на Saxon, где и скомпилированное выражение XPath, и собственная древовидная модель являются потокобезопасными, а в качестве бонуса вы получаете доступ к XPath 2.0.