本文將介紹RabbitMQ的binder提供的重試功能:重新入隊
準備一個會消費失敗的例子,可以直接沿用前文的工程,也可以新建一個,然後創建如下代碼的邏輯:
@EnableBinding(TestApplication.TestTopic.class)
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@RestController
static class TestController {
@Autowired
private TestTopic testTopic;
/**
* 消息生產接口
*
* @param message
* @return
*/
@GetMapping("/sendMessage")
public String messageWithMQ(@RequestParam String message) {
testTopic.output().send(MessageBuilder.withPayload(message).build());
return "ok";
}
}
/**
* 消息消費邏輯
*/
@Slf4j
@Component
static class TestListener {
private int count = 1;
@StreamListener(TestTopic.INPUT)
public void receive(String payload) {
log.info("Received payload : " + payload + ", " + count);
throw new RuntimeException("Message consumer failed!");
}
}
interface TestTopic {
String OUTPUT = "example-topic-output";
String INPUT = "example-topic-input";
@Output(OUTPUT)
MessageChannel output();
@Input(INPUT)
SubscribableChannel input();
}
}
內容很簡單,既包含了消息的生產,也包含了消息消費。消息消費的時候主動拋出了一個異常來模擬消息的消費失敗。
在啓動應用之前,還要記得配置一下輸入輸出通道對應的物理目標(exchange或topic名)、並設置一下分組,比如:
spring.cloud.stream.bindings.example-topic-input.destination=test-topic
spring.cloud.stream.bindings.example-topic-input.group=stream-exception-handler
spring.cloud.stream.bindings.example-topic-input.consumer.max-attempts=1
spring.cloud.stream.rabbit.bindings.example-topic-input.consumer.requeue-rejected=true
spring.cloud.stream.bindings.example-topic-output.destination=test-topic
完成了上面配置之後,啓動應用並訪問localhost:8080/sendMessage?message=hello接口來發送一個消息到MQ中了,此時可以看到程序不斷的拋出了消息消費異常。這是由於這裏我們多加了一個配置:spring.cloud.stream.rabbit.bindings.example-topic-input.consumer.requeue-rejected=true。在該配置作用之下,消息消費失敗之後,並不會將該消息拋棄,而是將消息重新放入隊列,所以消息的消費邏輯會被重複執行,直到這條消息消費成功爲止。