前面的学习都是基于原生的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. git进阶命令

    首先, clone 一个远端仓库,到其目录下: $ Git clone git://example.com/myproject $ cd myproject 然后,看看你本地有什么分支: $ git ...

  2. C++学习3--编程基础(vector、string、三种传参)

    知识点学习 Vector容器 vector是C++标准程序库中的一个类,其定义于头文件中,与其他STL组件一样,ventor属于STD名称空间: ventor是C++标准程序库里最基本的容器,设计之初 ...

  3. Ubuntu 分辨率显示出错,分辨率不是最佳分辨率的解决办法

    本文为转载,但在Ubuntu16.04LTS下亲测有效. (1)首先使用 xrandr 命令列出当前所能检测到的分辨率,如一台显示器,最佳分辨率为 1440x900(我的显示器尽量设置1680x105 ...

  4. mysql系列三、mysql开启缓存、设置缓存大小、缓存过期机制

    一.开启缓存 mysql 开启查询缓存可以有两种方法来开启一种是使用set命令来进行开启,另一种是直接修改my.ini文件来直接设置都是非常的简单的哦. 开启缓存,设置缓存大小,具体实施如下: 1.修 ...

  5. HTML学习笔记08-表格

    HTML表格 表格由<table>标签来定义,表格的行由<tr>标签来定义,表格的列由<td>标签来定义 <!DOCTYPE html> <htm ...

  6. python系统编码转换

    # coding:gbk import sys import locale def p(f): print '%s.%s(): %s' % (f.__module__, f.__name__, f() ...

  7. MariaDB:在Linux下修改编码

    参考网址:http://www.cnblogs.com/vingi/articles/4302330.html: # vi /etc/my.cnf [mysqld] init_connect='SET ...

  8. 微信支付之JsApi支付

    常见问题:金额错误,微信金额是int类型,最小单位为分,即是1 客户端调用微信支付的时候一闪而过:这个原因是因为微信商户后台支付目录地址没设置对,导致js调用的时候验证没通过 .aspx页面设置: x ...

  9. ES6 模块与 CommonJS 模块的差异

    ES6 模块与 CommonJS 模块完全不同.它们有两个重大差异 CommonJS 输出是值的拷贝,即原来模块中的值改变不会影响已经加载的该值,ES6静态分析,动态引用,输出的是值的引用,值改变,引 ...

  10. 使用JSONP实现跨域通信

    引语 Ajax 允许在不干扰 Web 应用程序的显示和行为的情况下在后台进行数据检索.Ajax 允许在不干扰 Web 应用程序的显示和行为的情况下在后台进行数据检索.由于受到浏览器的限制,该方法不允许 ...