Spring - 消息驱动的通道适配器 - 停止一个特定的并发消费者

时间:2014-11-13 20:47:34

标签: spring-integration

我使用spring集成组件来连接我的流程

  • 消息驱动的通道适配器从weblogic队列中选择消息。
  • 使用消息转换器并将消息丢弃到频道。

  • 来自频道的此消息由服务激活器选取。

  • 服务激活器上的pojo,从db执行一些数据处理,然后生成报告。

  • 由于某些原因,我想停止此消费者处理此请求的原因(例如pojo花费的时间过长)

我有什么选择?

  • 我试过这些:
    • 通过JMX暴露弹簧的消息驱动器通道适配器。
    • 在消息驱动的通道适配器上使用stop方法。
    • 这会阻止消息驱动的通道适配器选择好的新消息。
    • 但不会阻止一位消费者已经选择了该消息并且当前正在处理中。
    • 我怎样才能停止在我的pojo中花费太长时间的这个过程?

感谢任何帮助。


更新 - 2

这是我的代码。          

<bean id="myListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="destination" ref="requestQueue"/>
    <property name="concurrentConsumers" value="5"/>
    <property name="maxConcurrentConsumers" value="10"/>
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="taskExecutor" ref="threadPoolTaskExecutor"/>
    <property name="sessionTransacted" value="true"/>
</bean> 

    <bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="10" />
    <property name="maxPoolSize" value="50" />
    <property name="queueCapacity" value="10" />
    <property name="waitForTasksToCompleteOnShutdown" value="false"/>
</bean> 

<!-- Channel where service activator drops message to -->
<si:channel id="jmsOutChannel" />

<!-- This bean code calls DB to get some data and build a report/-->
<bean id="simpleExecutor" class="com.poc.reports.executors.SimpleCode"/>

<!-- Initialize service activator -->
<si:service-activator id="activator" input-channel="jmsInChannel"
    ref="simpleExecutor" method="execute" output-channel="jmsOutChannel">
</si:service-activator>

<!-- outbound adaptor for response Queue -->
<jms:outbound-channel-adapter id="jmsout"
    channel="jmsOutChannel" destination="responseQueue" />
  • 我发现正如你所提到的那样保持了交易。

  • 但是我看到创建了5到10个threadPoolTask​​Executors,因为我有并发使用者= 5-10(在适配器上)

  • 为什么要创建多个threadPoolTask​​Executors?它应该不只是使用一个threadpooltaskexecutor吗?
  • 如果我将并发使用者设为1,则会在会话交易后等待接收每条消息。

感谢您的回复。谢谢。


更新 - 3 - 与适配器一起使用时,在执行程序服务中维护事务可以完美地工作。

  • 关于杀死特定线程,我向执行服务添加了一个名为interruptNamedThread(String threadName)的方法,并通过JMX公开它。
  • 触发它并设置中断标志。
  • 我可以检查中断状态并通过返回来终止线程。(只是因为我的测试代码在循环中运行并且有机会检查中断状态)。

  • 然而,这对我的情况没有帮助。

  • 由于我的线程不在循环中运行。它与DB对话并生成报告。线程结束。返回池
  • 我想在从DB调用或第三方库调用(报告生成器)返回时间过长时结束该线程。
  • 在这种情况下,它没有机会检查中断标志,因为它卡在一个呼叫(DB或报告生成器)中。

在我的用例中,重新启动组件是杀死线程的唯一方法吗?

感谢任何建议。

1 个答案:

答案 0 :(得分:0)

您可以注入TaskExcecutor并将其waitForTasksToCompleteOnShutdown设置为false;这会导致它shutdown()方法在调用时调用基础shutdownNow()上的ExecutorService(或者注入ExecutorService并直接调用其shutdownNow()方法)。

这将取消(尝试中断)活动线程。

但是,如果您的服务正在做不可中断的事情,那么这将无济于事 - 例如......

synchronize(foo) {}

lock.lock()

...或从插座等读取。