Java 如何在Spring集成中最好地实现DynamicPoller
我有一个接收大消息的流(在RDBMS表中),所以我不能在给定时间处理太多这些消息。因此,我使用Java 如何在Spring集成中最好地实现DynamicPoller,java,spring,spring-integration,Java,Spring,Spring Integration,我有一个接收大消息的流(在RDBMS表中),所以我不能在给定时间处理太多这些消息。因此,我使用限制处理,并且使用一些队列,其容量设置为。我知道多个线程/事务将参与这个流,对于用例来说,这是可以接受的 轮询DB的查询需要一些时间才能运行,因此我不希望运行的次数超过我需要的次数。此外,该流接收的消息往往以“突发”的形式出现,这意味着它可能会收到1000条消息,但在一个小时内不会收到任何消息 我想做的是使用一个动态轮询器,它将不经常轮询(因为如上所述,查询运行成本很高),除非我看到我收到了大量消息,在
限制处理,并且使用一些队列
,其容量设置为
。我知道多个线程/事务将参与这个流,对于用例来说,这是可以接受的
轮询DB的查询需要一些时间才能运行,因此我不希望运行的次数超过我需要的次数。此外,该流接收的消息往往以“突发”的形式出现,这意味着它可能会收到1000条消息,但在一个小时内不会收到任何消息
我想做的是使用一个动态轮询器
,它将不经常轮询(因为如上所述,查询运行成本很高),除非我看到我收到了大量消息,在这种情况下,我希望非常频繁地轮询,直到处理完所有消息。例如,如果我有
,并且我知道轮询器刚刚读取了100条消息,那么RDBMS中有更多需要处理的消息的可能性很大,我应该在处理完成后立即再次轮询
我知道Spring没有提供一种方法来修改触发器
,使其在本质上具有动态性,并且已经研究了Spring集成参考“
在动态轮询器示例项目:
这是一个开始,但我确实需要轮询器根据当前负载更改频率。
关于这一点,我可能不太正确,但我认为Gary在关于“”的演讲中提到的类似内容可能会很有趣。
无论如何,编写一个类来更改轮询器的频率似乎不是什么大问题。更具挑战性的是,如何知道何时发生了轮询,但由于没有任何结果发布到输出通道,因此没有结果
我考虑过的一些选择:
将
连接到调用
的轮询器的频道。Service activator检查消息的数量,并调整DynamicPeriodicTrigger上轮询器的时段
。
问题是,若并没有收到任何消息,这将永远不会被调用,所以一旦我调整轮询频率,轮询周期将保持不确定
与#1相同,但向DynamicPeriodicTrigger
添加逻辑,该逻辑将在下一次触发发生后或在特定时间段后将周期
恢复为初始延迟
将
元素中的
元素与MethodInterceptor
实现一起使用。
类似于Artem在本文中的建议。
虽然这允许我进入receive
方法的前面,但它不允许我访问receive
方法的结果(这将为我提供检索到的消息数量)。请注意,Gary在本文中提到的内容似乎证实了这一点
请求处理程序建议链是一个特例;我们必须注意只建议内部端点方法,而不是任何下游处理(在输出通道上)
建议轮询器更简单,因为我们建议整个流程。如“7.1.4命名空间支持”小节“AOP建议链”中所述,您只需通过实现MethodInterceptor接口创建建议
有关非常简单的建议,请参见SourcePollingChannelAdapterFactoryBeanTests.testAdviceChain()
代码:
添加(新方法拦截器(){
公共对象调用(MethodInvocation调用)抛出可丢弃的{
adviceappliced.set(true);
返回调用。继续();
}
});
这只是用来断言通知被正确调用;真正的通知将在调用之前和/或之后添加代码。继续()
实际上,此建议建议所有方法,但只有一个(Callable.call()
)
返回
通知后创建一个,该通知带有一个查找Message receive()
方法的切入点
克隆JdbcPollingChannelAdapter
并在新类中添加我的挂钩
也许加里在这方面的建议会有用,但“要点”链接不再有效
更新:
我最终实现的选项是在returningadvice
之后使用类似以下内容的。
原始代码:
<int-jdbc:inbound-channel-adapter id="jdbcInAdapter"
channel="inputChannel" data-source="myDataSource"
query="SELECT column1, column2 from tableA"
max-rows-per-poll="100">
<int:poller fixed-delay="10000"/>
</int-jdbc:inbound-channel-adapter>
新代码:
<bean id="jdbcDynamicTrigger" class="DynamicPeriodicTrigger">
<constructor-arg name="period" value="20000" />
</bean>
<bean id="jdbcPollerMetaData" class="org.springframework.integration.scheduling.PollerMetadata">
<property name="maxMessagesPerPoll" value="1000"/>
<property name="trigger" ref="jdbcDynamicTrigger"/>
</bean>
<bean id="pollMoreFrequentlyForHighVolumePollingStrategy" class="springintegration.scheduling.PollMoreFrequentlyForHighVolumePollingStrategy">
<property name="newPeriod" value="1"/>
<property name="adjustmentThreshold" value="100"/>
<property name="pollerMetadata" ref="jdbcPollerMetaData"/>
</bean>
<aop:config>
<aop:aspect ref="pollMoreFrequentlyForHighVolumePollingStrategy" >
<aop:after-returning pointcut="bean(jdbcInAdapterBean) and execution(* *.receive(..))" method="afterPoll" returning="returnValue"/>
</aop:aspect>
</aop:config>
<bean id="jdbcInAdapterBean" class="org.springframework.integration.jdbc.JdbcPollingChannelAdapter">
<constructor-arg ref="myDataSource" />
<constructor-arg value="SELECT column1, column2 from tableA" />
<property name="maxRowsPerPoll" value="100" />
</bean>
<int:inbound-channel-adapter id="jdbcInAdapter" ref="jdbcInAdapterBean"
channel="inputChannel"
auto-startup="false">
<int:poller ref="jdbcPollerMetaData" />
</int:inbound-channel-adapter>
如果JIRA没有实现,并且有人对我实现的代码感兴趣,请对此添加评论,我将在github或gist上提供代码。感谢打开JIRA问题;我们应该在那里讨论该功能,因为堆栈溢出不适合扩展对话
但是,我不确定您上面所说的“……但是”gist“链接不再有效……”。它对我来说很好……但是让我们在JIRA中讨论。是的,您是对的,gist链接仍然有效。在打开此问题时,它似乎被我使用的浏览器内部阻止。