Spring拆分器/聚合器处理异常

时间:2014-07-31 13:46:48

标签: spring spring-integration

版本:spring-integration-core - 2.2.3

以下是我的拆分器/聚合器设置的简化版本。

<task:executor id="taskExecutor" pool-size="${pool.size}"
               queue-capacity="${queue.capacity}" 
       rejection-policy="CALLER_RUNS" keep-alive="120"/>

<int:channel id="service-requests"/>
<int:channel id="service-request"/>
<int:channel id="channel-1">
    <int:dispatcher task-executor="taskExecutor" failover="false"/>
</int:channel>
<int:channel id="channel-2">
    <int:dispatcher task-executor="taskExecutor" failover="false"/>
</int:channel>


<int:gateway id="myServiceRequestor" default-reply-timeout="${reply.timeout}"
             default-reply-channel="service-aggregated-reply"
             default-request-channel="service-request"
             service-interface="com.blah.blah.MyServiceRequestor"/>

<int:splitter input-channel="service-request"
              ref="serviceSplitter" output-channel="service-requests"/>

<!-- To split the request and return a java.util.Collection of Type1 and Type2 -->
<bean id="serviceSplitter" class="com.blah.blah.ServiceSplitter"/>


<int:payload-type-router input-channel="service-requests" resolution-required="true">
    <int:mapping
            type="com.blah.blah.Type1"
            channel="channel-1"/>
    <int:mapping
            type="com.blah.blah.Type2"
            channel="channel-2"/>
</int:payload-type-router>

<!-- myService is a bean where processType1 & processType2 method is there to process the payload -->
<int:service-activator input-channel="channel-1"
                       method="processType1" output-channel="service-reply" requires-reply="true"
                       ref="myService"/>

<int:service-activator input-channel="channel-2"
                       method="processType2" output-channel="service-reply" requires-reply="true"
                       ref="myService"/>

<int:publish-subscribe-channel id="service-reply" task-executor="taskExecutor"/>

<!-- myServiceAggregator has a aggregate method which takes a Collection as argument(aggregated response from myService) -->
<int:aggregator input-channel="service-reply"
                method="aggregate" ref="myServiceAggregator"
                output-channel="service-aggregated-reply"
                send-partial-result-on-expiry="false"
                message-store="myResultMessageStore"
                expire-groups-upon-completion="true"/>

<bean id="myResultMessageStore" class="org.springframework.integration.store.SimpleMessageStore" />

<bean id="myResultMessageStoreReaper" class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="myResultMessageStore" />
    <property name="timeout" value="2000" />
</bean>

<task:scheduled-tasks>
    <task:scheduled ref="myResultMessageStoreReaper" method="run" fixed-rate="10000" />
</task:scheduled-tasks>

如果mySevice中的processType1 / processType2方法抛出RuntimeException,那么它会尝试将消息发送到错误通道(我相信spring默认情况下会这样做)并且错误通道中的消息有效负载保持在堆中并且不会变为垃圾收集。

更新了更多信息: 我对错误频道的评论。我调试了代码,发现ErrorHandlingTaskExecutor正在尝试使用MessagePublishingErrorHandler,它将消息发送到MessagePublishingErrorHandler.resolveErrorChannel方法返回的通道。

来自ErrorHandlingTaskExecutor.java的代码片段

public void execute(final Runnable task) {
    this.executor.execute(new Runnable() {
        public void run() {
            try {
                task.run();
            }
            catch (Throwable t) {
                errorHandler.handleError(t);   /// This is the part which sends the message in to error channel.
            }
        }
    });
}

来自MessagePublishingErrorHandler.java的代码片段

public final void handleError(Throwable t) {
    MessageChannel errorChannel = this.resolveErrorChannel(t);
    boolean sent = false;
    if (errorChannel != null) {
        try {
            if (this.sendTimeout >= 0) {
                sent = errorChannel.send(new ErrorMessage(t), this.sendTimeout);
.....

当我进行堆转储时,我总是看到对有效负载消息的引用(我相信它保留在上面的通道中)并且没有得到GC。

想知道处理这种情况的正确方法是什么,或者我的配置中是否缺少任何内容? 如果服务激活器方法抛出任何异常,也可以告诉spring丢弃有效负载(而不是将其发送到错误通道)?

期待您的投入。

感谢。

1 个答案:

答案 0 :(得分:1)

您的网关上没有定义error-channel因此我们不会将其发送到那里,我们只会向调用者抛出异常。

但是,部分组位于聚合器中,永远不会完成。您需要配置MessageGroupStoreReaper as shown in the reference manual(或在Spring Integration 4.0.x中设置group-timeout)以丢弃部分组。

相关问题