在开发过程中 ,
多应用监听同一队列,连接的数据库不同,最终生产者逻辑出现错误,口头的约定不太靠得住,所以我想要解决这个问题
我的想法是让指定的ip才能去消费指定的队列,试了两种方式
第一种方式:
消息中放ip,消费端获取到ip不符就放回队列,但是这个有两个问题;1手动放置消息需要把缺认改为手动,这会使消息重试机制失效,2重回队列在文档上的说明是重回尽可能的靠近原来的位置,不一定是原来的位置,所以不能用这种方式
第二种方式:
在项目启动时检查自身ip,符合就将队列添加到容器里,反之不加;我采用的是这一种
代码如下
//依赖
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
消费者
/***
* @ClassName: Config
* @Description: TODO
* @Auther: jzc
* @Date: 2020/8/26 19:30
* @version : V1.0
*/
@Configuration
public class Config {
//自己想要指定消费的ip
@Value("${consumer.ip}")
private String consumerIp;
@Bean
public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) throws UnknownHostException {
//实例化容器
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
//自动确认,设置手动会让 消息重试失效,没有重试需求的随意
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
//默认重回队列,false,这个我还有点疑问 false就对了
container.setDefaultRequeueRejected(false);
//获取本机ip
String ip = InetAddress.getLocalHost().getHostAddress();
// 配置重试
container.setAdviceChain(createRetry());
//验证ip
if (consumerIp.equals(ip)) {
container.setQueueNames("hello.world.queue");
container.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
System.out.println("====接收到" + message.getMessageProperties().getConsumerQueue() + "队列的消息=====");
//异常,模拟失败 触发失败重试
throw new RuntimeException();
}
});
}
return container;
}
private RetryOperationsInterceptor createRetry() {
return RetryInterceptorBuilder
.stateless()
//重试次数
.maxAttempts(3)
//重试间隔 指数递增时间参数 最大间隔时间
.backOffOptions(5000, 3, 5000)
//次数用完之后的处理,用的是默认处理类,我设了死信,所以失败消息会到死信
.recoverer(new RejectAndDontRequeueRecoverer())
.build();
}
}
yml
spring:
rabbitmq:
host: 12345678
port: 5672
username: guest
password: guest
virtual:
host: /
cache:
channel:
size: 100
consumer:
ip: 1234567