Spring boot 每x分钟从驼峰队列消费一次
试图实现一种方法,使我的消费者每隔30分钟左右从队列接收消息。 在上下文中,我的错误队列中有20条消息,直到x分钟过去,然后我的路由将使用队列中的所有消息并继续“睡眠”,直到另外30分钟过去 不确定实现这一点的最佳方式,我尝试了spring@Scheduled、camel timer等,但都没有达到我的期望。我一直在尝试让它与路由策略一起工作,但在正确的功能中没有骰子。它似乎会立即从队列中消耗掉Spring boot 每x分钟从驼峰队列消费一次,spring-boot,apache-camel,Spring Boot,Apache Camel,试图实现一种方法,使我的消费者每隔30分钟左右从队列接收消息。 在上下文中,我的错误队列中有20条消息,直到x分钟过去,然后我的路由将使用队列中的所有消息并继续“睡眠”,直到另外30分钟过去 不确定实现这一点的最佳方式,我尝试了spring@Scheduled、camel timer等,但都没有达到我的期望。我一直在尝试让它与路由策略一起工作,但在正确的功能中没有骰子。它似乎会立即从队列中消耗掉 路由策略是正确的路径还是可以使用其他路径?从队列读取的路由将始终尽可能快地读取任何消息 您可以做的一
路由策略是正确的路径还是可以使用其他路径?从队列读取的路由将始终尽可能快地读取任何消息 您可以做的一件事是启动/停止或挂起使用消息的路由,因此进行以下设置:
route 1: error_q_reader, which goes from('jms').
route 2: a timed route that fires every 20 mins
管线2可以使用组件启动管线
from('timer?20mins') // or whatever the timer syntax is...
.to("controlbus:route?routeId=route1&action=start")
这里最棘手的部分是知道什么时候停止这条路线。你让它运行5分钟吗?消息全部用完后是否要停止?可能有一种方法可以运行另一个路由来检查队列深度(比如每1分钟左右),如果它为0,则关闭路由1
,您可能会让它工作,但我可以向您保证,当您尝试处理大量异步操作时,这将变得混乱
您还可以尝试一些更奇特的方法,比如定制的
QueueBrowseStrategy
,它可以在队列上没有消息时触发事件关闭route 1
从队列读取的路由将始终以尽可能快的速度读取任何消息
您可以做的一件事是启动/停止或挂起使用消息的路由,因此进行以下设置:
route 1: error_q_reader, which goes from('jms').
route 2: a timed route that fires every 20 mins
管线2可以使用组件启动管线
from('timer?20mins') // or whatever the timer syntax is...
.to("controlbus:route?routeId=route1&action=start")
这里最棘手的部分是知道什么时候停止这条路线。你让它运行5分钟吗?消息全部用完后是否要停止?可能有一种方法可以运行另一个路由来检查队列深度(比如每1分钟左右),如果它为0,则关闭路由1
,您可能会让它工作,但我可以向您保证,当您尝试处理大量异步操作时,这将变得混乱
您还可以尝试一些更奇特的方法,比如定制的
QueueBrowseStrategy
,它可以在队列上没有消息时触发事件关闭route 1
我构建了一个customer bean来清空队列并关闭,但这不是一个非常优雅的解决方案,我很想找到一个更好的解决方案
public class TriggeredPollingConsumer {
private ConsumerTemplate consumer;
private Endpoint consumerEndpoint;
private String endpointUri;
private ProducerTemplate producer;
private static final Logger logger = Logger.getLogger( TriggeredPollingConsumer.class );
public TriggeredPollingConsumer() {};
public TriggeredPollingConsumer( ConsumerTemplate consumer, String endpoint, ProducerTemplate producer ) {
this.consumer = consumer;
this.endpointUri = endpoint;
this.producer = producer;
}
public void setConsumer( ConsumerTemplate consumer) {
this.consumer = consumer;
}
public void setProducer( ProducerTemplate producer ) {
this.producer = producer;
}
public void setConsumerEndpoint( Endpoint endpoint ) {
consumerEndpoint = endpoint;
}
public void pollConsumer() throws Exception {
long count = 0;
try {
if ( consumerEndpoint == null ) consumerEndpoint = consumer.getCamelContext().getEndpoint( endpointUri );
logger.debug( "Consuming: " + consumerEndpoint.getEndpointUri() );
consumer.start();
producer.start();
while ( true ) {
logger.trace("Awaiting message: " + ++count );
Exchange exchange = consumer.receive( consumerEndpoint, 60000 );
if ( exchange == null ) break;
logger.trace("Processing message: " + count );
producer.send( exchange );
consumer.doneUoW( exchange );
logger.trace("Processed message: " + count );
}
producer.stop();
consumer.stop();
logger.debug( "Consumed " + (count - 1) + " message" + ( count == 2 ? "." : "s." ) );
} catch ( Throwable t ) {
logger.error("Something went wrong!", t );
throw t;
}
}
}
配置bean,然后从计时器调用bean方法,并配置直接路由来处理队列中的条目
from("timer:...")
.beanRef("consumerBean", "pollConsumer");
from("direct:myRoute")
.to(...);
然后,它将读取队列中的所有内容,并在一分钟内没有条目到达时立即停止。您可能希望缩短时间,但我发现,如果JMS速度有点慢,那么它将在排干队列的中途超时
from("timer:...")
.beanRef("consumerBean", "pollConsumer");
from("direct:myRoute")
.to(...);
我也一直在研究
sjms批处理组件,以及它如何与pollEnrich
模式一起使用,但到目前为止,我还没能让它发挥作用。我构建了一个客户bean来排出队列并关闭,但这不是一个非常优雅的解决方案,我很想找到一个更好的解决方案
public class TriggeredPollingConsumer {
private ConsumerTemplate consumer;
private Endpoint consumerEndpoint;
private String endpointUri;
private ProducerTemplate producer;
private static final Logger logger = Logger.getLogger( TriggeredPollingConsumer.class );
public TriggeredPollingConsumer() {};
public TriggeredPollingConsumer( ConsumerTemplate consumer, String endpoint, ProducerTemplate producer ) {
this.consumer = consumer;
this.endpointUri = endpoint;
this.producer = producer;
}
public void setConsumer( ConsumerTemplate consumer) {
this.consumer = consumer;
}
public void setProducer( ProducerTemplate producer ) {
this.producer = producer;
}
public void setConsumerEndpoint( Endpoint endpoint ) {
consumerEndpoint = endpoint;
}
public void pollConsumer() throws Exception {
long count = 0;
try {
if ( consumerEndpoint == null ) consumerEndpoint = consumer.getCamelContext().getEndpoint( endpointUri );
logger.debug( "Consuming: " + consumerEndpoint.getEndpointUri() );
consumer.start();
producer.start();
while ( true ) {
logger.trace("Awaiting message: " + ++count );
Exchange exchange = consumer.receive( consumerEndpoint, 60000 );
if ( exchange == null ) break;
logger.trace("Processing message: " + count );
producer.send( exchange );
consumer.doneUoW( exchange );
logger.trace("Processed message: " + count );
}
producer.stop();
consumer.stop();
logger.debug( "Consumed " + (count - 1) + " message" + ( count == 2 ? "." : "s." ) );
} catch ( Throwable t ) {
logger.error("Something went wrong!", t );
throw t;
}
}
}
配置bean,然后从计时器调用bean方法,并配置直接路由来处理队列中的条目
from("timer:...")
.beanRef("consumerBean", "pollConsumer");
from("direct:myRoute")
.to(...);
然后,它将读取队列中的所有内容,并在一分钟内没有条目到达时立即停止。您可能希望缩短时间,但我发现,如果JMS速度有点慢,那么它将在排干队列的中途超时
from("timer:...")
.beanRef("consumerBean", "pollConsumer");
from("direct:myRoute")
.to(...);
我也一直在研究sjms批处理组件,以及如何将其与pollEnrich
模式一起使用,但到目前为止,我还无法使其正常工作。我已经解决了这一问题,通过在微服务方法中将我的应用程序用作CronJob,并赋予它优雅地自行关闭的能力,我们可以设置属性camel.springboot.duration max idle seconds
。因此,您的JMS使用者路由保持简单
另一种方法是声明一个路由来控制JMS使用者路由的“生命周期”(开始、睡眠和恢复)
我强烈建议您使用第一种方法。我已经解决了这个问题,通过将我的应用程序作为MicroServices方法中的CronJob,并赋予它优雅地关闭自身的能力,我们可以设置属性camel.springboot.duration max idle seconds
。因此,您的JMS使用者路由保持简单
另一种方法是声明一个路由来控制JMS使用者路由的“生命周期”(开始、睡眠和恢复)
我强烈建议您使用第一种方法。如果您使用,您可以利用它的优势
只需将JMS属性AMQ\u SCHEDULED\u delay
设置为延迟的毫秒数,就可以延迟代理上的消息传递。骑骆驼很容易
.setHeader("AMQ_SCHEDULED_DELAY", 60000)
它并不完全是您想要的,因为它不会每30分钟清空一个队列,而是将每个消息延迟30分钟
请注意,您必须在代理配置中启用schedulerSupport
。否则,将忽略延迟属性
<broker brokerName="localhost" dataDirectory="${activemq.data}" schedulerSupport="true">
...
</broker>
...
如果您使用它,您可以利用它的功能
只需将JMS属性AMQ\u SCHEDULED\u delay
设置为延迟的毫秒数,就可以延迟代理上的消息传递。骑骆驼很容易
.setHeader("AMQ_SCHEDULED_DELAY", 60000)
它并不完全是您想要的,因为它不会每30分钟清空一个队列,而是将每个消息延迟30分钟
请注意,您必须在brok中启用调度程序支持