使用事务将消息发送到异步服务

时间:2012-02-17 11:32:30

标签: spring spring-transactions spring-integration

我有一个持久的事务性队列,包含我需要通过异步协议发送的消息。每条消息都需要在自己的事务中发送,但是在给定时间在线的消息数量排除了使用每个消息的消息,而吞吐量要求排除了持续存在的中间消息的状态。

查看JmsTransactionManager的代码,我看到它正在使用TransactionSynchronizationManager,它将交易资源存储在ThreadLocal中。因此,似乎我需要实现一个PlatformTransactionManager来以某种方式在单个线程中管理多个事务。这个似乎有点极端......

是否有一些Spring Integration单元可以避免这种复杂性? 我应该更喜欢看JTA / XA吗?

1 个答案:

答案 0 :(得分:1)

Spring Integration中所有这些基于队列的通道都只在默认情况下将消息存储在内存中。当需要持久性时,您可以在“message-store”元素中提供“queue”属性以引用持久性MessageStore实现,也可以将本地通道替换为持久性支持的属性。代理,例如JMS支持的通道或通道适配器。后一个选项允许您利用任何JMS提供程序的实现来实现消息持久性。

您可以通过添加message-store属性为任何QueueChannel配置邮件存储,如下所示。

Spring Integration通过以下方式提供对消息存储模式的支持:a)定义org.springframework.integration.store.MessageStore策略接口,b)提供此接口的多个实现,以及c)在具有该功能的所有组件上公开消息存储属性缓冲消息,以便您可以注入任何实现MessageStore接口的实例。

我的示例使用了JDBC Message Store,但也有其他一些选项可供使用。

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${my.jdbc.driver}"/>
    <property name="url" value="${my.jdbc.url}"/>
    <property name="username" value="${my.jdbc.username}"/>
    <property name="password" value="${my.jdbc.password}"/>
    <property name="minEvictableIdleTimeMillis" value="300000"/>
    <property name="timeBetweenEvictionRunsMillis" value="60000"/>
    <property name="connectionProperties" value="SetBigStringTryClob=true;"/>
</bean>

<!-- The poller is needed by any of the QueueChannels -->
<integration:poller id="myPoller" fixed-rate="5000" default="true"/>

<!-- The MessageStore is needed to persist messages used by any of the QueueChannels -->
<int-jdbc:message-store id="myMessageStore" data-source="myDataSource" table-prefix="MY_INT_"/>

<!-- Main entry point into the process -->
<integration:gateway id="myGateway"
                     service-interface="com.mycompany.myproject.integration.gateways.myGateway"
                     default-request-channel="myGatewayChannel"
        />

<!-- Map the initial input channel to the first step, MyFirstService -->
<integration:channel id="myGatewayChannel">
    <integration:queue capacity="1000"/>
    <integration:queue message-store="myMessageStore" capacity="1000"/>
</integration:channel>

<!-- Step 1: My First Service -->
<integration:service-activator
        id="myFirstServiceActivator"
        input-channel="myGatewayChannel"
        output-channel="myNextChannel"
        ref="myFirstService"
        method="process"/>    

<!-- LONG running process. Setup asynchronous queue channel. -->
<integration:channel id="myNextChannel">
    <integration:queue capacity="1000"/>
    <integration:queue message-store="myMessageStore" capacity="1000"/>
</integration:channel>