Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring boot 仅从@RabbitListener获取特定消息_Spring Boot_Spring Amqp_Spring Rabbit - Fatal编程技术网

Spring boot 仅从@RabbitListener获取特定消息

Spring boot 仅从@RabbitListener获取特定消息,spring-boot,spring-amqp,spring-rabbit,Spring Boot,Spring Amqp,Spring Rabbit,我有一个向RabbitMQ发送消息的遗留系统。 系统只使用一个队列:q.finance.invoice,但它有两种消息类型,其中消息类型在标头上可用 第一类 Type : invoice.created { "field_1" : "", "field_2" : "", } 第二类 Type : invoice.paid { "field_5" : "", "field_6" : "", } 因此,现在我的消费者需要根据数据类型有选择地处理消息。 Spring有@Rabbi

我有一个向RabbitMQ发送消息的遗留系统。 系统只使用一个队列:
q.finance.invoice
,但它有两种消息类型,其中消息类型在标头上可用

第一类

Type : invoice.created
{
  "field_1" : "",
  "field_2" : "",
}
第二类

Type : invoice.paid

{
  "field_5" : "",
  "field_6" : "",
}
因此,现在我的消费者需要根据数据类型有选择地处理消息。 Spring有
@RabbitHandler
可以做到这一点。。。如果消息是由spring发布的。 但是我不能使用
@RabbitHandler
注释。 我认为这是因为
@RabbitHandler
正在基于旧式系统中不存在的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

如何模拟这种
@RabbitHandler
行为(根据其类型获取数据)

所以我使用
@RabbitListener
来使用消息。 但是
@RabbitListener
正在接收所有类型的消息。 我们使用
@RabbitListener
的另一个原因是,我们的错误处理程序依赖于
消息
频道
我们的基本方法是:

@RabbitListener(queues=“q.finance.invoice”)
public void listenInvoicePaid(消息消息、频道、@Header(AmqpHeaders.DELIVERY_标记)长标记){
//将消息体JSON字符串转换为对象
//处理它
}
我正在尝试根据类型进行手动拒绝,这很有效。但我确信,当我有许多侦听器或队列时,它是不可伸缩的

import java.io.IOException;
导入org.apache.commons.lang3.StringUtils;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.amqp.core.Message;
导入org.springframework.amqp.rabbit.annotation.RabbitListener;
导入org.springframework.amqp.support.AmqpHeaders;
导入org.springframework.messaging.handler.annotation.Header;
导入org.springframework.stereotype.Service;
导入com.rabbitmq.client.Channel;
@服务
公共类InvoiceListenerOnMethod{
私有静态最终记录器log=LoggerFactory.getLogger(InvoiceListenerOnMethod.class);
@RabbitListener(queues=“q.finance.invoice”)
public void listenInvoiceCreated(消息消息、频道、@Header(AmqpHeaders.DELIVERY_标记)长标记)
抛出IOException{
如果(!StringUtils.equalsIgnoreCase(“invoice.created”,message.getMessageProperties().getType())){
log.warn(“[on方法]拒绝创建的发票:{}”,消息);
channel.basicject(标记,true);
返回;
}
info(“[on方法]创建的侦听发票:{}”,消息);
}
@RabbitListener(queues=“q.finance.invoice”)
public void listenInvoicePaid(消息消息、频道、@Header(AmqpHeaders.DELIVERY_标记)长标记)
抛出IOException{
如果(!StringUtils.equalsIgnoreCase(“invoice.paid”,message.getMessageProperties().getType())){
log.warn(“[on Method]拒绝支付的发票:{}”,消息);
channel.basicject(标记,true);
返回;
}
log.info(“[on方法]监听发票:{}”,消息);
}
}
请看,如果我有4条消息(付费创建),侦听器可以运行4次以上,因为我们无法控制谁将接收哪条消息。因此,对于
listenInvoicePaid()

  • 拒绝
  • 拒绝
  • ack()
  • 拒绝
  • ack()
同样,ack()之前的多次拒绝()也可以在
listenInvoiceCreated()中发生
因此,在所有信息正确处理之前,我总共可以收到10条左右的信息


有没有修复代码的建议?

我还没有使用rabbit的spring integration,但总而言之,拥有一个处理不同消息类型的单一队列的想法听起来有问题:

许多消费者可能会收到他们无法处理的类型的消息,并且必须拒绝它们,这样消息就会返回到rabbit,然后一次又一次。。。所有集群的性能都可能因此而恶化

所以我认为有两条路可以走:

  • 实现可以处理两种消息类型的单个侦听器。无需更改Rabbit,但在java方面可能是一个具有挑战性的重构

  • 幸运的是,rabbitmq在路由消息方面非常灵活。将exchange配置为根据路由密钥、头将A类型的消息路由到队列A,将B类型的消息路由到队列B,无论什么,Rabbit中都有不同类型的exchange,您肯定会找到适合您的最佳配置


我个人会选择第二条路径。

我没有使用rabbit的spring集成,但总的来说,拥有一个处理不同消息类型的单一队列的想法听起来像是有问题的:

许多消费者可能会收到他们无法处理的类型的消息,并且必须拒绝它们,这样消息就会返回到rabbit,然后一次又一次。。。所有集群的性能都可能因此而恶化

所以我认为有两条路可以走:

  • 实现可以处理两种消息类型的单个侦听器。无需更改Rabbit,但在java方面可能是一个具有挑战性的重构

  • 幸运的是,rabbitmq在路由消息方面非常灵活。将exchange配置为根据路由密钥、头将A类型的消息路由到队列A,将B类型的消息路由到队列B,无论什么,Rabbit中都有不同类型的exchange,您肯定会找到适合您的最佳配置


我个人会选择第二条路径。

您可以向容器工厂的
afterReceiveMessagePostProcessor
属性添加
MessagePostProcessor
。在邮政专业