Java 使用rabbitmq的Spring引导故障转移重试程序:未能调用目标方法
实际上,我正在尝试使用rabbit mq实现故障转移重试器功能 因此,要求是从队列中获取消息并对其进行处理。如果出现任何问题,则需要再次重试该消息3次 谁能帮我解决这个问题 这是我的密码 POJOJava 使用rabbitmq的Spring引导故障转移重试程序:未能调用目标方法,java,spring-boot,rabbitmq,spring-rabbit,Java,Spring Boot,Rabbitmq,Spring Rabbit,实际上,我正在尝试使用rabbit mq实现故障转移重试器功能 因此,要求是从队列中获取消息并对其进行处理。如果出现任何问题,则需要再次重试该消息3次 谁能帮我解决这个问题 这是我的密码 POJO package com.poc.failoverretryer.model; import java.io.Serializable; public class User implements Serializable { private String firstname; pr
package com.poc.failoverretryer.model;
import java.io.Serializable;
public class User implements Serializable {
private String firstname;
private String lastname;
private String dob;
public User(String firstname, String lastname, String dob) {
this.firstname = firstname;
this.lastname = lastname;
this.dob = dob;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
@Override
public String toString() {
return "User{" +
"firstname='" + firstname + '\'' +
", lastname='" + lastname + '\'' +
", dob='" + dob + '\'' +
'}';
}
}
配置文件
package com.poc.failoverretryer.config;
import com.poc.failoverretryer.model.User;
import com.poc.failoverretryer.receiver.Receiver;
import com.poc.failoverretryer.receiver.ReceiverTwo;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.io.Serializable;
@Configuration
public class RMQConfiguration implements Serializable {
@Value("${data.incoming.x}")
String EXCHANGE_NAME;
@Value("${data.dl.x}")
String DEAD_LETTER_EXCHANGE_NAME;
@Value("${incoming.queue}")
String INCOMING_QUEUE_NAME;
@Value("${data.incoming.two}")
String INCOMING_QUEUE_TWO_NAME;
@Value("${data.dl}")
String DEAD_LETTER_QUEUE_NAME;
@Value("${data.dl.two}")
String DEAD_LETTER_QUEUE_TWO_NAME;
@Value("${data.parking}")
String PARKING_LOT_QUEUE_NAME;
@Value("${retry.delay:3000}")
public long DELAYED_RETRY_TIME;
@Value("${max.retry:3}")
public int MAX_RETRY_ATTEMPTS;
@Primary
@Bean
Queue queue() {
return QueueBuilder.durable(INCOMING_QUEUE_NAME)
.deadLetterExchange(DEAD_LETTER_EXCHANGE_NAME)
.build();
}
@Bean
Queue queueTwo() {
return QueueBuilder.durable(INCOMING_QUEUE_TWO_NAME)
.deadLetterExchange(DEAD_LETTER_EXCHANGE_NAME)
.build();
}
@Bean
Queue deadLetterQueue() {
return QueueBuilder.durable(DEAD_LETTER_QUEUE_NAME)
.deadLetterExchange(EXCHANGE_NAME)
.withArgument("x-message-ttl", DELAYED_RETRY_TIME)
.build();
}
@Bean
Queue deadLetterTwoQueue() {
return QueueBuilder.durable(DEAD_LETTER_QUEUE_TWO_NAME)
.deadLetterExchange(EXCHANGE_NAME)
.withArgument("x-message-ttl", DELAYED_RETRY_TIME)
.build();
}
@Bean
Queue parkingLotQueue() {
return new Queue(PARKING_LOT_QUEUE_NAME, true);
}
@Bean
DirectExchange exchange() {
return new DirectExchange(EXCHANGE_NAME);
}
@Bean
DirectExchange deadLetterExchange() {
return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME);
}
@Bean
Binding binding(@Qualifier("queue") Queue queue, @Qualifier("exchange") DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(INCOMING_QUEUE_NAME);
}
@Bean
Binding bindingTwo(@Qualifier("queueTwo") Queue queue, @Qualifier("exchange") DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(INCOMING_QUEUE_TWO_NAME);
}
@Bean
Binding deadLetterBinding(@Qualifier("deadLetterQueue") Queue queue, @Qualifier("deadLetterExchange") DirectExchange exchange) {
return BindingBuilder
.bind(queue)
.to(exchange).with(INCOMING_QUEUE_NAME);
}
@Bean
Binding deadLetterTwoBinding(@Qualifier("deadLetterTwoQueue") Queue queue, @Qualifier("deadLetterExchange") DirectExchange exchange) {
return BindingBuilder
.bind(queue)
.to(exchange).with(INCOMING_QUEUE_TWO_NAME);
}
@Bean
@Qualifier("myRabbitListenerContainer")
SimpleMessageListenerContainer myRabbitListenerContainer(ConnectionFactory connectionFactory, @Qualifier("messageListenerAdapter") MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(INCOMING_QUEUE_NAME);
container.setMessageListener(listenerAdapter);
return container;
}
@Bean
@Qualifier("myRabbitListenerTwoContainer")
SimpleMessageListenerContainer myRabbitListenerTwoContainer(ConnectionFactory connectionFactory, @Qualifier("messageListenerTwoAdapter") MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(INCOMING_QUEUE_TWO_NAME);
container.setMessageListener(listenerAdapter);
return container;
}
@Primary
@Bean
MessageListenerAdapter messageListenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Bean
MessageListenerAdapter messageListenerTwoAdapter(ReceiverTwo receiverTwo) {
return new MessageListenerAdapter(receiverTwo, "receiveMessageTwo");
}
}
**听众呢**
package com.poc.failoverretryer.receiver;
import com.poc.failoverretryer.config.RMQConfiguration;
import com.poc.failoverretryer.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Component
public class Receiver {
Logger logger = LoggerFactory.getLogger(Receiver.class);
@Autowired
private RabbitTemplate rabbitTemplate;
@Value("${max.retry:3}")
public int MAX_RETRY_ATTEMPTS;
@Value("${data.parking}")
String PARKING_LOT_QUEUE_NAME;
public void receiveMessage(Message message, @Header(required = false, name = "x-death") List<Map<String, Object>> xDeath) throws InterruptedException {
System.out.println("Received <" + message + ">");
logger.info(String.valueOf(xDeath));
if (message == null) {
System.out.println("The message is null");
return;
}
try {
process(message.getBody());
} catch (Exception e) {
if (checkIfNeedToRetry(xDeath))
throw new AmqpRejectAndDontRequeueException("Failed to process message");
else
rabbitTemplate.convertAndSend(PARKING_LOT_QUEUE_NAME, message);
}
}
private void process(byte[] message) throws Exception {
throw new Exception("Test");
}
private boolean checkIfNeedToRetry(List<Map<String, Object>> xDeath) {
long retryCount = 0L;
if (xDeath != null) {
Optional<Long> count = xDeath.stream()
.flatMap(m -> m.entrySet().stream())
.filter(e -> e.getKey().equals("count"))
.findFirst().map(e -> (Long) e.getValue());
retryCount = count.map(Long::longValue).orElse(retryCount);
// if (count.isPresent()) {
// retryCount = count.get().longValue();
// System.out.println("Retry: " + retryCount);
// } else {
//
// }
}
System.out.println(retryCount);
if (retryCount <= MAX_RETRY_ATTEMPTS) {
System.out.println("Retrying");
return true;
} else {
System.out.println("exceed max retry " + retryCount + " -> sending to parking lot");
return false;
}
}
}
public void receiveMessage(Message Message,@Header(required=false,name=“x-death”)列表xDeath)引发中断异常{
您不能将@Header
与旧式侦听器适配器一起使用,后者只能与@RabbitListener
方法一起使用
无论如何都不需要它;您可以从
message.getMessageProperties().getXDeathHeader();
public void receiveMessage(消息消息,@Header(required=false,name=“x-death”)List xDeath)引发中断异常{
您不能将@Header
与旧式侦听器适配器一起使用,后者只能与@RabbitListener
方法一起使用
无论如何都不需要它;您可以从
message.getMessageProperties().getXDeathHeader();
是否有可能使用自定义对象并使用旧侦听器获取xDeath?
public void receiveMessage(用户)抛出InterruptedException
,因为配置中与SimpleMessageListenerContainer
一起使用的@Header
抛出相同的转换错误否;对于旧适配器,您要么获得完整的消息,要么仅获得转换后的有效负载。您必须使用@RabbitListener
进行丰富的参数映射。是否存在是否有可能使用自定义对象并使用旧侦听器获取xDeath?public void receiveMessage(用户)抛出InterruptedException
,因为配置中与SimpleMessageListenerContainer
一起使用的@Header
抛出相同的转换错误否;对于旧适配器,您要么得到完整的消息,要么只得到转换后的负载。必须使用@RabbitListener
进行丰富的参数映射。