Spring集成消息丢失场景

时间:2018-11-15 16:30:09

标签: spring spring-integration message loss

摘要-系统关闭应用程序期间消息丢失。

我有一个用Spring集成编写的应用程序,并且正在使用'jms:message-driven-channel-adapter'来接收来自外部系统的请求。这是通道适配器的配置-

<jms:message-driven-channel-adapter id="InboundAdapter" destination="InQueue"
                                        connection-factory="connectionFactory"
                                        channel="responseChannel"
                                        error-channel="errorChannel"
                                        acknowledge="transacted"
                                        receive-timeout="50000"
                                        auto-startup="true"/>

我的回复频道如下所示-

 <int:chain id="processorChain" input-channel="responseChannel">
        <int:service-activator method="doProcess" ref="inputProcessor" />

        <int:router id="inputRouter" method="route">
            <int:mapping value="REQUIRED" channel="builderChannel"/>
            <int:mapping value="NOT_REQUIRED" channel="TerminateChannel"/>
            <bean id="Router" class="xxx.xxx.Router">
            </bean>
        </int:router>
    </int:chain>

现在,当我执行“ kill -9 pid”时,我看到消息已回滚到队列,这一切都很好。但是当我执行“ kill pid”时,消息丢失了。我启用了jms日志,可以看到JMS侦听器在关闭JMS使用者之前正在等待传输中的消息完成,但是仍然没有消息回滚到我的队列中。这是我在日志中看到的日志片段

跟踪:15.11.18 15:42:46.619 [Thread-10]调试org.springframework.jms.listener.DefaultMessageListenerContainer-等待消息侦听器调用程序关闭 跟踪:15.11.18 15:42:46.619 [Thread-10]调试org.springframework.jms.listener.DefaultMessageListenerContainer-仍在等待关闭1个消息侦听器调用程序(迭代0)

此日志记录之后,它将调用在响应通道中定义的服务激活器。

有人可以说明上述行为吗?我期望当我们发出kill命令时,正在传输的所有消息都应回滚到队列中,而不是与此相反,它正在尝试调用定义为在频道中,并调用了路由器的最后一个组件后,它就结束了。

任何有关此主题的帮助将非常有帮助!


在进行了一些进一步的调试之后,我对系统进行了深入研究,我发现了发生这种情况的确切情况。让我直通看看是否有意义。当触发系统性关闭时,JMS将等待传输中的消息完成,然后再停止应用程序,直到此时一切都很好。目前,该链正在执行-

<int:chain input-channel="inputchain">
    <int:transformer id="xxx" method="transform">
        <bean class="xxx" />
    </int:transformer>

    <int:service-activator  id="xxx" method="doProcess">
        <bean class="xx">
            <constructor-arg ref="xxx"/>
        </bean>
    </int:service-activator>

    <int:service-activator id="xxx" ref="rulesProcessor" method="doProcess"/>
    <int:service-activator id="xxx" ref="xxx" method="doProcess"/>

    <!-- Existing Flow Continues -->
    <int:router id="xxxRequiredRouter" method="xxxRequired">
        <int:mapping value="Required" channel="firstChannel"/>
        <int:mapping value="NotRequired" channel="secondChannel"/>
        <bean id="xxxRouter" class="xxx.Router" />
        </bean>
    </int:router>

</int:chain>

<int:chain input-channel="secondChannel">

   some logic

</int:chain>

因此线程完成了此链并正常退出。它没有将我的下一个链称为“ secondChannel”。我的交易边界未在此链“ inputchain”上完成,而是在secondChannel的末尾完成。因此,由于事务边界位于下一个链的末尾,因此我没有将这种转换提交给数据库,因此在数据库中不可用,并且应用程序认为链执行已完成,因此已完成,因此不会回滚到队列中。也一样因此,到最后,我的数据库中没有此消息,并且它不在队列中。

是这样的情况,只有关闭触发时正在执行的链会完成,并且不会将处理委托给后续链吗?

1 个答案:

答案 0 :(得分:0)

杀死SIGTERM将等待线程完成其工作。

最终,容器会中断它,但这只会在它正在执行可中断的操作时有所帮助。