前面的学习都是基于原生的api,下面我们使用spingboot来整合rabbitmq

springboot对rabbitmq提供了友好支持,极大的简化了开发流程

引入maven


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

配置yml


rabbitmq:
host: 47.102.103.232
port: 5672
username: admin
password: admin
virtual-host: /test
publisher-confirms: true
publisher-returns: true
cache:
channel:
size: 10
listener:
simple:
acknowledge-mode: manual
concurrency: 1
max-concurrency: 3
retry:
enabled: true

这是基础的配置,看不懂的配置后面会介绍

更详细的配置参考官方https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#boot-features-rabbitmq(搜索rabbit往下拉即可)

代码实现


配置类

@Configuration
public class RabbitConfig {
@Bean
public Queue helloQueue() {
return new Queue("helloQueue");
}
   //创建topic交换机
@Bean
public TopicExchange helloExchange() {
return new TopicExchange("helloExchange");
}
@Bean
public Binding bindingPaymentExchange(Queue helloQueue, TopicExchange helloExchange) {
return BindingBuilder.bind(helloQueue).to(helloExchange).with("hello.#");
}
/**
* 定制化amqp模版
   * connectionFactory:包含了yml文件配置参数
*/
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
// 必须设置为 true,不然当 发送到交换器成功,但是没有匹配的队列,不会触发 ReturnCallback 回调
// 而且 ReturnCallback 比 ConfirmCallback 先回调,意思就是 ReturnCallback 执行完了才会执行 ConfirmCallback
rabbitTemplate.setMandatory(true);
// 设置 ConfirmCallback 回调 yml需要配置 publisher-confirms: true
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
       // 如果发送到交换器都没有成功(比如说删除了交换器),ack 返回值为 false
// 如果发送到交换器成功,但是没有匹配的队列(比如说取消了绑定),ack 返回值为还是 true (这是一个坑,需要注意)
if (ack) {
String messageId = correlationData.getId();
System.out.println("confirm:"+messageId);
}
});
// 设置 ReturnCallback 回调 yml需要配置 publisher-returns: true
// 如果发送到交换器成功,但是没有匹配的队列,就会触发这个回调
rabbitTemplate.setReturnCallback((message, replyCode, replyText,
exchange, routingKey) -> {
String messageId = message.getMessageProperties().getMessageId();
System.out.println("return:"+messageId);
});
return rabbitTemplate;
}
}
回调机制
  • 消息不管是否投递到交换机都进行ConfirmCallback回调,投递成功ack=true,否则为false
  • 交换机匹配到队列成功则不进行ReturnCallback回调,否则先进行ReturnCallback回调再进行ConfirmCallback回调
  • 如果消息成功投递到交换机,但没匹配到队列,则ConfirmCallback回调ack仍为true

生产者

@Component
public class RbProducer {
//注意一定要使用RabbitTemplate!!
//虽然RabbitTemplate实现了AmqpTemplate 但是AmqpTemplate里并没有能发送correlationData的方法
@Resource
private RabbitTemplate rbtemplate;
public void send1(String msg){
//CorrelationData用于confirm机制里的回调确认
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
rbtemplate.convertAndSend("helloExchange", "hello.yj", msg,correlationData);
}
public void send2(User user){
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
rbtemplate.convertAndSend("helloExchange", "hello.yj", user,correlationData);
}
}

消费者

@Component
@RabbitListener(queues = "helloQueue")
public class RbConsumer {
@RabbitLister(queues = "helloQueue")
public void receive0(Message msg, Channel channel) throws IOException {
System.out.println("consumer receive message0: " + msg);
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
}
@RabbitHandler
public void receive1(String msg, @Header(AmqpHeaders.DELIVERY_TAG)long deliveryTag, Channel channel) throws IOException {
System.out.println("consumer receive message1: " + msg);
channel.basicAck(deliveryTag, false);
}
@RabbitHandler
public void receive2(User user, @Header(AmqpHeaders.DELIVERY_TAG)long deliveryTag, Channel channel) throws IOException {
System.out.println("consumer receive message2: "+user);
     //如果发生以下情况投递消息所有的通道或连接被突然关闭(包括消费者端丢失TCP连接、消费者应用程序(进程)挂掉、通道级别的协议异常)任何已经投递的消息但是没有被消费者端确认的消息会自动重新排队。
//请注意,连接检测不可用客户端需要一段时间才会发现,所以会有一段时间内的所有消息会重新投递
//因为消息的可能重新投递,所有必须保证消费者端的接口的幂等。 //在RabbitMQ中影响吞吐量最大的参数是:消息确认模式和Qos预取值
//自动消息确认模式或设置Qos预取值为无限虽然可以最大的提高消息的投递速度,但是在消费者端未及时处理的消息的数量也将增加,从而增加消费者RAM消耗,使用消费者端奔溃。所以以上两种情况需要谨慎使用。
//RabbitMQ官方推荐Qos预取值设置在 100到300范围内的值通常提供最佳的吞吐量,并且不会有使消费者奔溃的问题
channel.basicAck(deliveryTag, false);
channel.basicQos(100);
// 代表消费者拒绝一条或者多条消息,第二个参数表示一次是否拒绝多条消息,第三个参数表示是否把当前消息重新入队
// channel.basicNack(deliveryTag, false, false);
// 代表消费者拒绝当前消息,第二个参数表示是否把当前消息重新入队
// channel.basicReject(deliveryTag,false);
}
}

@RabbitListener+@RabbitHandler:消费者监听

  使用@RabbitListener+@RabbitHandler组合进行监听,监听器会根据队列发来的消息类型自动选择处理方法

channel.basicAck(deliveryTag, false):手动确认机制

  deliverTag:该消息的标识,每来一个消息该标识+1

  multiple:第二个参数标识书否批量确认

  requeue:被拒绝的是否重新入队

channel.basicQos(100):最多未确认的消息数量为100,超过100队列将停止给该消费者投递消息

更多参数详解参考https://www.cnblogs.com/piaolingzxh/p/5448927.html

测试


@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestBoot.class)
public class TestRabbit {
@Resource
private RbProducer producer;
@Test
public void send1() {
producer.send1("hello,im a string");
}
@Test
public void send2() {
User user = new User();
user.setNickname("hello,im a object");
producer.send2(user);
}
}

成功消费

完结

下篇博客我们讨论下在拥有了手动ack机制、confirm机制、return机制后,是否真的可靠~

rabbitmq学习(七) —— springboot下的可靠使用的更多相关文章

  1. RabbitMQ学习在windows下安装配置

    RabbitMQ学习一. 在windows下安装配置 1.下载并安装erlang,http://www.erlang.org/download.html,最新版是R15B01(5.9.1).由于我机器 ...

  2. SpringBoot学习(七)-->SpringBoot在web开发中的配置

    SpringBoot在web开发中的配置 Web开发的自动配置类:在Maven Dependencies-->spring-boot-1.5.2.RELEASE.jar-->org.spr ...

  3. RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理

    上一篇已经讲了Rabbitmq如何在Windows平台安装 不懂请移步: RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 一.理论 .net环境下,C#代码订阅 ...

  4. rabbitmq学习(五):springboot整合rabbitmq

    一.Springboot对rabbitmq的支持 springboot提供了对rabbitmq的支持,并且大大简化了rabbitmq的相关配置.在springboot中,框架帮我们将不同的交换机划分出 ...

  5. RabbitMQ学习总结 第三篇:工作队列Work Queue

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  6. RabbitMQ学习总结 第二篇:快速入门HelloWorld

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  7. (转)RabbitMQ学习

    (二期)24.消息中间件RabbitMq [课程24]RabbitM...概念.xmind60.2KB [课程24]五种队列模式.xmind0.8MB [课程24]消息确...rm).xmind84. ...

  8. 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群

    在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...

  9. 官网英文版学习——RabbitMQ学习笔记(一)认识RabbitMQ

    鉴于目前中文的RabbitMQ教程很缺,本博主虽然买了一本rabbitMQ的书,遗憾的是该书的代码用的不是java语言,看起来也有些不爽,且网友们不同人学习所写不同,本博主看的有些地方不太理想,为此本 ...

随机推荐

  1. Java打印M图形(二维数组)——(九)

    对于平面图形输出集合图形与数字组合的,用二维数组.先在Excel表格中分析一下,找到简单的规律.二维数组的行数为行高,列数为最后一个数大小. 对于减小再增大再减小再增大的,可以用一个boolean标志 ...

  2. mysql系列六、mysql创建用户、授权、备份及恢复命令

    一.创建用户和授权 下面的操作中,其中someusername为用户名,somepassword为密码,somedbname为数据库名 1.创建用户 create user 'someusername ...

  3. Python3学习笔记19-继承和多态

    在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承, 新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Sup ...

  4. Sql 正确删除用户过期的数据

    怎样才算是正确的删除过期的数据呢?先交代一下前提,XX网站上面有一个放心企业专区,办理超级会员即可成为放心企业,放心企业可设置推荐职位展示在放心企业专区,信息都是存放在Info表中的,所谓的推荐职位就 ...

  5. C/C++:函数调用规则__stdcall,__cdecl,__pascal,__fastcall

    __cdecl __cdecl 是 C Declaration  的缩写,表示 C 语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈.被调用函数不会要求调用者传递多 ...

  6. MyEclipse中如何配置默认jsp为UTF-8格式

  7. table下tbody滚动条与thead对齐的方法且每一列可以不均等

    1 前言 table下tbody滚动条与thead对齐的方法,开始在tbody的td和thead的tr>td,对每一个Item加入百分比,结果是没对齐.也尝试了用bootstrap的col-md ...

  8. centos7忘记登录密码修改

    很多时候我们都会忘记Linux root 用户的口令,下面就教大家如果忘记root口令怎么办 第1步:开机后在内核上按“e”.截图如下 按e以后会进入内核启动页面,如下图 第2步:在linux16这行 ...

  9. mysql5.7安装教程图解

    启动安装包: 左边是你电脑上可以连接到mysql的软件,比如Visual Studio,Eclipse,PyCharm等,中间是需求的版本或者额外组件,右边是状态. 选择一个选项,然后点击下面的che ...

  10. jQuery性能优化指南

    总是从ID选择器开始继承在jQuery中最快的选择器是ID选择器,因为它直接来自于JavaScript的getElementById()方法. 例如有一段HTML代码:代码 <div id=&q ...