SprinngBoot整合rabbitmq(一)

SprinngBoot整合rabbitmq

基于springboot 2.x

一、概述

1、简介

RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿里巴巴公司的,现已经转让给apache).

RabbitMQ是对高级消息队列协议(Advanced Message Queueing Protocol, AMQP)的实现

AMQP 的工作过程如下图:消息(message)被发布者(publisher)发送给交换机(exchange),交换机常常被比喻成邮局或者邮箱。然后交换机将收到的消息根据路由规则分发给绑定的队列(queue)。最后AMQP代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。

image.png

2、交换机
NameDefault pre-declared names
Direct exchange(Empty string) and amq.direct
Fanout exchangeamq.fanout
Topic exchangeamq.topic
Headers exchangeamq.match (and amq.headers in RabbitMQ)

Direct 直连交换机:

​ 直连型交换机(direct exchange)是根据消息携带的路由键(routing key)将消息投递给对应队列的。直连交换机用来处理消息的单播路由(unicast routing)(尽管它也可以处理多播路由)。

image.png

fanout扇形交换机:

​ 扇型交换机(funout exchange)将消息路由给绑定到它身上的所有队列,而不理会绑定的路由键。如果N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的拷贝分别发送给这所有的N个队列。

image.png

topic 主题交换机:

​ 主题交换机(topic exchanges)通过对消息的路由键和队列到交换机的绑定模式之间的匹配,将消息路由给一个或多个队列。主题交换机经常用来实现各种分发/订阅模式及其变种。主题交换机通常用来实现消息的多播路由(multicast routing)。

3、队列

AMQP中的队列(queue)跟其他消息队列或任务队列中的队列是很相似的:它们存储着即将被应用消费掉的消息。队列跟交换机共享某些属性,但是队列也有一些另外的属性。

  • Name
  • Durable(消息代理重启后,队列依旧存在)
  • Exclusive(只被一个连接(connection)使用,而且当连接关闭后队列即被删除)
  • Auto-delete(当最后一个消费者退订后即被删除)
  • Arguments(一些消息代理用他来完成类似与TTL的某些额外功能)

队列在声明(declare)后才能被使用。如果一个队列尚不存在,声明一个队列会创建它。如果声明的队列已经存在,并且属性完全相同,那么此次声明不会对原有队列产生任何影响。如果声明中的属性与已存在队列的属性有差异,那么一个错误代码为406的通道级异常就会被抛出。

4、工作流程

1、建立信息。Publisher定义需要发送消息的结构和内容。

2、建立Conection和Channel。由Publisher和Consumer创建连接,连接到Broker的物理节点上,同时建立Channel。Channel是建立在Connection之上的,一个Connection可以建立多个Channel。Publisher连接Virtual Host 建立Channel,Consumer连接到相应的Queue上建立Channel。

3、声明交换机和队列。声明一个消息交换机(Exchange)和队列(Queue),并设置相关属性。

4、发送消息。由Publisher发送消息到Broker中的Exchange中

5、路由转发。RabbitMQ收到消息后,根据消息指定的Exchange(交换机) 来查找Binding(绑定) 然后根据规则(Routing Key)分发到不同的Queue。这里就是说使用Routing Key在消息交换机(Exchange)和消息队列(Queue)中建立好绑定关系,然后将消息发送到绑定的队列中去。

6、消息接收。Consumer监听相应的Queue,一旦Queue中有可以消费的消息,Queue就将消息发送给Consumer端。

7、消息确认。当Consumer完成某一条消息的处理之后,需要发送一条ACK消息给对应的Queue。

Consumer收到消息时需要显式的向RabbitMQ Broker发送basic.ack消息或者Consumer订阅消息时设置auto_ack参数为true。

在通信过程中,队列对ACK的处理有以下几种情况:

如果Consumer接收了消息,发送ack,RabbitMQ会删除队列中这个消息,发送另一条消息给Consumer。

如果Consumer接收了消息, 但在发送ack之前断开Channel,RabbitMQ会认为这条消息没有被deliver(递送),如果有其他的Channel,会该消息将被发送给另外的Channel。如果没有,当在Consumer再次连接的时候,这条消息会被redeliver(重新递送)。

如果consumer接收了消息,但是忘记了ack,RabbitMQ不会重复发送消息。

新版RabbitMQ还支持Consumer reject某条(类)消息,可以通过设置requeue参数中的reject为true达到目地,那么Consumer将会把消息发送给下一个注册的Consumer。

8、关闭消息通道(channel)以及和服务器的连接。

二、简单示例

交换机,队列,路由都已经设置完毕。如果没有设置的话,可以再配置类中进行配置。

1、字符串数据

1.导入amqp依赖

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

2.设置访问地址,端口及相关配置。

spring.rabbitmq.host=host
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

3.使用 RabbitTemplate测试一下。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DirectTests {
    @Autowired
   RabbitTemplate rabbitTemplate;
    @Test
    public void test(){
        rabbitTemplate.convertAndSend("msg","Hello my message");
    }
}

4.以上信息已经发送到消息队列中,在rabbitmq的客户端可以查看。也可以取出来,

@RabbitListener(queues = “msg”)监听到队列中有消息传入就会执行,消息体会封装到参数中。

或者使用receiveAndConvert,本方法可以接受并转化成原来的数据。

@Component
public class DirectReceiver {
    @RabbitListener(queues = "msg")
    public void receiver(String msg){
        System.out.println("msg:"+msg);
    }
}

2、对象数据及序列化

对普通字符串数据直接传输,但是对象数据则会序列化。默认采用jdk序列化。

1.准备一个测试用的实体类,实现了序列化接口。

public class User implements Serializable {
    private Integer id;
    private String name;
    private String gender;

  
    public User(Integer id, String name, String gender) {
        this.id = id;
        this.name = name;
        this.gender = gender;
    }

    public User() {
    }
}

2.测试类中传入对象。

 @Test
    public void test1(){
        User user=new User(10,"tony","male");
        rabbitTemplate.convertAndSend("rbmq.direct","queue01",user);

    }

3.此时消息队列客户端确实可以接受到数据,但是数据是序列化的,不适合阅读。

我们可以用配置类,将其转化为json序列化。此时在客户端查看到的就是json数据。

@Configuration
public class QueueConfiguration {
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        return rabbitTemplate;
    }

}

4.接受数据,这里我们使用@RabbitListener注解接受到的数据是没有转化的。所以我们使用receiveAndConvert方法。

 @Test
    public void rece(){
        Object o = rabbitTemplate.receiveAndConvert("rbmq.queue01");
        System.out.println(o);

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值