Java Spring集成-网关-拆分器-带JMS的聚合器

Java Spring集成-网关-拆分器-带JMS的聚合器,java,spring-integration,Java,Spring Integration,我正在尝试使用spring集成以JMS支持的事件驱动方式执行网关-->拆分器-->ServiceActivator-->聚合器模式。我希望ServiceActivator是多线程的,任何端点都可以在集群上执行,而不一定是在原始服务器上执行。我可以在单个JVM中实现这一点,而无需使用JMS(使用SI通道),但我知道SI通道无法帮助我水平扩展,即多个VM <bean id="processOutputQueue" class="org.apache.activemq.command.Activ

我正在尝试使用spring集成以JMS支持的事件驱动方式执行网关-->拆分器-->ServiceActivator-->聚合器模式。我希望ServiceActivator是多线程的,任何端点都可以在集群上执行,而不一定是在原始服务器上执行。我可以在单个JVM中实现这一点,而无需使用JMS(使用SI通道),但我知道SI通道无法帮助我水平扩展,即多个VM

<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />
这是我到目前为止的配置

    <int:gateway id="transactionGateway" default-reply-channel="transaction-reply"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int-jms:outbound-gateway id="transactionJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="transaction-request"
    request-destination="transactionInputQueue" reply-channel="transaction-reply"
    reply-destination="transactionOutputQueue" extract-reply-payload="true"
    extract-request-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000"
        max-messages-per-task="1" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway for Splitter -->
<int-jms:inbound-gateway id="splitterGateWay"
    request-destination="transactionInputQueue" request-channel="splitter-input"
    reply-channel="splitter-output" concurrent-consumers="1"
    default-reply-destination="processInputQueue"
    max-concurrent-consumers="1" extract-reply-payload="true"
    correlation-key="JMSCorrelationID" extract-request-payload="true" />

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" concurrent-consumers="1"
    default-reply-destination="processOutputQueue"
    max-concurrent-consumers="1" extract-reply-payload="true"
    correlation-key="JMSCorrelationID" extract-request-payload="true"
    max-messages-per-task="1" />

<int-jms:inbound-gateway id="aggregatorGateway"
    request-destination="processOutputQueue" request-channel="aggregator-input"
    reply-channel="aggregator-output" concurrent-consumers="1"
    default-reply-destination="transactionOutputQueue"
    max-concurrent-consumers="1" extract-reply-payload="true"
    extract-request-payload="true" max-messages-per-task="1"
    correlation-key="JMSCorrelationID" />


<int:splitter id="transactionSplitter" input-channel="splitter-input"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>

<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" method="aggregate" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>
<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />
我将JMS管道仅限于服务激活器,这正是我最初想要的

<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />
基于上述方法,我唯一的问题是,即使我跨多个VM使用聚合器,我是否也需要数据库支持聚合器(因为它前面的JMS网关确保它只接收具有有效关联ID的消息?)

<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />

关于,

您可能不需要在每个组件之间使用JMS。然而,我们有很多这样的链式网关的测试用例,并且都可以正常工作

<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />
有些东西一定是接线错误了。由于您没有显示完整的配置,因此很难推测

<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />

确保使用最新版本(2.2.4)并打开调试日志记录,并通过流跟踪消息;只要您的消息负载可以跨JMS边界识别,就应该很容易找出哪里出了问题。

感谢您的响应。我将研究建议。您是否知道有任何示例可以使用JMS支持的这种模式。我通过将JMS队列仅保留给服务激活器来实现这一点。但是,对于这种模式,我不确定是否应该使用数据库/缓存支持的聚合器(因为网关处理的是将消息响应与相同ID关联起来)。
<bean id="processOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.process.output" />
</bean>

<bean id="transactionOutputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.result" />
</bean>

<bean id="transactionInputQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test.com.abc.transaction.input" />
</bean>

<int:gateway id="transactionGateway"
    default-request-channel="transaction-request" default-reply-timeout="10000"
    default-reply-channel="aggregator-output"
    service-interface="com.test.abc.integration.service.ProcessGateway">
</int:gateway>

<int:splitter id="transactionSplitter" input-channel="transaction-request"
    ref="processSplitter" output-channel="splitter-output">
</int:splitter>


<int-jms:outbound-gateway id="splitterJMSGateway"
    correlation-key="JMSCorrelationID" request-channel="splitter-output"
    request-destination="processInputQueue" reply-channel="aggregator-input"
    reply-destination="processOutputQueue" extract-request-payload="true"
    extract-reply-payload="true">
    <int-jms:reply-listener
        max-concurrent-consumers="20" receive-timeout="5000" />
</int-jms:outbound-gateway>

<!-- Inbound Gateway Invokes Service Activator and Sends response back to 
    the channel -->
<int-jms:inbound-gateway id="seriveActivatorGateway"
    request-destination="processInputQueue" request-channel="process-input"
    reply-channel="process-output" default-reply-destination="processOutputQueue"
    concurrent-consumers="5" max-concurrent-consumers="10"
    extract-reply-payload="true" correlation-key="JMSCorrelationID"
    extract-request-payload="true" max-messages-per-task="1" />

<int:service-activator id="jbpmServiceActivator"
    input-channel="process-input" ref="jbpmService" requires-reply="true"
    output-channel="process-output">
</int:service-activator>


<int:aggregator id="transactionAggregator"
    input-channel="aggregator-input" ref="processAggregator"
    output-channel="aggregator-output" message-store="processResultMessageStore"
    send-partial-result-on-expiry="false">
</int:aggregator>

<bean id="processResultMessageStore"
    class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="processResultMessageStoreReaper"
    class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="processResultMessageStore" />
    <property name="timeout" value="5000" />
</bean>
<task:scheduled-tasks>
    <task:scheduled ref="processResultMessageStoreReaper"
        method="run" fixed-rate="1000" />
</task:scheduled-tasks>

<int:logging-channel-adapter id="logger"
    level="DEBUG" log-full-message="true" />

<int-stream:stdout-channel-adapter
    id="stdoutAdapter" channel="logger" />