我正在使用Spring-cloud-stream和RabbitMQ。
我有一个生成消息的REST端点。
@SpringBootApplication
@EnableBinding(MyProcessor.class)
public class ProducerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ProducerDemoApplication.class, args);
}
}
@RestController
class ProducerController {
@Autowired
MyProcessor myProcessor;
@RequestMapping(value = "sendmessage/{message}", method = RequestMethod.GET)
public String sendMessage(@PathVariable("message") String message) {
myProcessor.anOutput().send(MessageBuilder.withPayload(message).build());
return "sent";
}
}
interface MyProcessor {
String INPUT = "myInput";
@Output("myOutput")
MessageChannel anOutput();
}
通过另一个应用程序,我正在使用这些消息。
@StreamListener(MyProcessor.INPUT)
public void eventHandler(String message) {
System.out.println("************** Message received => "+message);
}
当两个应用程序都启动并运行时。我能够发布消息并在消费者处使用它。
在以下情况下我面临的问题:
我故意让消费者失望,并通过生产者发布消息。现在,当消费者启动时,它没有收到任何消息。
我想RabbitMQ保证消息传递。
Github链接
https://github.com/govi20/producer-demo
https://github.com/govi20/consumer-demo
答案 0 :(得分:1)
您需要在使用者输入绑定上分组。否则,它是匿名的,并绑定自动删除队列,该队列仅在使用者运行时存在。
答案 1 :(得分:1)
正如我之前提到的,由于没有@Input
配置,因此在使用者启动期间出现A component required a bean named 'myInput' that could not be found.
错误,因此'myInput'中已经有配置错误。
因此,在消费者方面需要这样的事情
interface MyProcessor {
String INPUT = "myInput";
@Input("myInput")
MessageChannel myInput();
}
如果您没有定义group
,还会在Rabbit端产生匿名队列(类似myInput.anonymous.pZg03h0zQ2-SHLh1_QL8DQ
),这实际上在每次启动时都会导致队列名称不同,所以
spring.cloud.stream.bindings.myInput.destination=myInput
spring.cloud.stream.bindings.myInput.group=myGroup
将导致队列名称myInput.myGroup
在启动之间是持久且一致的。
此外,在生产者端myOutput
上创建了一个Rabbit Exchange,它没有路由到上述(或任何其他)队列,因此Rabbit丢弃了消息,因此您不可能接收到始发的消息从生产者开始,直到您在myOutput
交换和myInput.myGroup
队列之间创建路由。
但是,如果您如上所述配置输入,spring-cloud-stream还将创建一个名为myInput
的交换,该交换将自动路由到myInput.myGroup
,因此,如果您将生产者更改为发送给该交换者目的地,您将收到有关消费者的消息。