• RabbitMQ入门


    RabbItMQ核心概念:

    ​ RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,RabbitMQ是用Erlang语言来编写的,并且RabbitMQ是基于AMQP协议的。

    1、RabbitMQ的高性能之道是如何做到的?

    ​ Erlang语言最初在于交换机领域的架构模式,这样使得RabbitMQ在Broker之间进行数据交互的性能是非常优秀的。

    ​ Erlang的优点:Erlang有着和原生Socket一样的延迟。

    2、什么是AMQP高级消息队列协议?

    ​ AMQP:是具有现代特征的二进制协议。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

    AMQP核心概念:

    • Server:又称Broker,接受客户端的连接,实现AMQP实体服务

    • Connection:连接,应用程序与Broker的网络连接

    • Channel:网络信道,几乎所有的操作都在Channel中进行,Channel是进行消息读写的通道。客户端可建立多个Channel,每个Channel代表一个会话任务。

    • Message:消息,服务器和应用程序之间传送的数据,由Properties和Body组成。Properties可以对消息进行修饰,比如消息的优先级、延迟等高级特性;Body则就是消息体内容。

    • Virtual host:虚拟地址,用于进行逻辑隔离,最上层的消息路由。一个Virtual Host里面可以有若干个Exchange和Queue,同一个Virtual host里面不能有相同名称的Exchange和Queue。

    • Exchange:交换机,接收消息,根据路由键转发消息到绑定的队列

    • Binding:Exchange和Queue之间的虚拟连接,binding中可以包含Routing key

    • Routing Key :一个路由规则,虚拟机可以用它来确定如何路由一个特定消息。

    • Queue:也称为Message Queue,消息队列,保存消息并将它们转发给消费者

    3、RabbitMQ消息是如何流转的?

    4、Exchange交换机详解

    ​ 接收消息,并根据路由键转发消息到所绑定的队列。

    交换机属性:

    • Name:交换机名称

    • Type:交换机类型为direct、topic、fanout、headers

      • Direct Exchange:所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue(不需要进行任何绑定操作)

      • Topic Exchage:所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定Topic的Queue上,Exchange将RouteKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic。

    Fanout Exchange:

    ​ 1、不处理路由键,只需要简单的将队列绑定到交换机上

    	2、发送到交换机的消息都会被转发到与该交换机绑定的所有队列上
    

    ​ 3、Fanout交换机转发消息是最快的。(不做任何匹配处理)

    Queue-消息队列

    • 消息队列,实际存储消息数据
    • Durability:是否持久化,Durable:是,Transient:否
    • Auto delete:如选yes,代表当最后一个监听被移除后,该Queue会自动被删除

    Virtual host-虚拟主机:

    • 虚拟地址,用于进行逻辑隔离,最上层的消息路由
    • 一个Virtual Host里面可以有若干个Exchange和Queue
    • 同一个Virtual Host里面不能有相同名称的Exchange和Queue

    RabbitMQ高级特性:

    1、消息如何保障100%的投递成功?

    • 消息落库,对消息状态进行打标

    • 消息的延迟投递,做二次确认,回调检查

    2、消费端—幂等性保障

    • 唯一ID+指纹码机制

      好处:实现简单

      坏处:高并发下有数据库写入的性能瓶颈

      解决方案:根据id进行分库分表进行算法路由

    • 利用redis原子特性实现

    3、Confirm确认消息

    理解Comfirm消息确认机制:

    • 消息的确认,是指生产者投递消息后,如果Broker收到消息,则会给我们生产者一个应答。
    • 生产者进行接收应答,用来确定这条消息是否正常的发送到Broker,这种方式也是消息的可靠性投递的核心保障!

    如何实现Confirm确认消息?

    ​ 第一步:在channel上开启确认模式:channel.confirmSelect()

    ​ 第二步:在channel上添加监听:addConfirmListener,监听成功和失败的 返回结果,根据具体的结果对消息进行重新发送、或记录日志等后续处理!

    Return消息机制:Return Listener 用于处理一些不可路由的消息!

    • 被 broker 接收到只能表示 message 已到达服务器,并不能保证消息一定会被投递到目标 queue。所以还需 returnCallback 。
    • 我们的消息生产者,通过指定一个Exchange和RoutingKey,把消息送达到其一个队列中去,然后我们的消费者监听队列,进行消费处理操作!
    • 但是在某些情况下,如果我们在发送消息的时候,当前的Exchange不存在或者指定的路由key路由不到,这个时候如果我们需要监听这种不可达的消息,就要使用Return Listener!

    4、TTL队列、消息

    • TTL是Time To Live的缩写,也就是生存时间
    • RabbitMQ支持消息的过期时间,在消息发送时可以进行指定
    • RabbitMQ支持队列的过期时间,从消息入队列开始计算,只要超过队列超时时间配置,那么消息会自动的清除

    5、死信队列

    利用DLX,当消息在一个队列中变成了死信之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX。

    消息变成死信有以下几种情况:

    • 消息被拒绝,并且requeue=false
    • 消息TTL过期
    • 队列达到最大长度

    6、RabbitMQ的使用场景:

    1、跨系统的异步通信

    ​ 2、多个应用之间的耦合

    ​ 3、应用内的同步变异步

    ​ 4、消息驱动的架构

    ​ 5、应用需要更灵活的耦合方式

    ​ 6、跨局域网

    Springboot整合RabbitMQ

    消息提供者:

    先导入相对应的依赖

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

    然后编写消息提供者的配置文件

    #对于rabbitMQ的支持
    spring.rabbitmq.host=127.0.0.1
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest
    #项目的名称
    spring.application.name=rabbitmq-provider
    

    再编写消息提供者的配置类,写好消息的队列、交换机、绑定策略等

    @Configuration
    public class RabbitConfig {
    
        @Bean
        public Queue TestDirectQueue(){
            return new Queue("TestDirectQueue1111",true);
        }
    
        @Bean
        public DirectExchange TestDirectExchange(){
            return new DirectExchange("TestDirectExchange",true,false);
        }
        @Bean
        public Binding bindingDirect() {
            return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
        }
        @Bean
        DirectExchange lonelyDirectExchange() {
            return new DirectExchange("lonelyDirectExchange");
        }
    }
    

    最后在编写消息提供者的接口层

    @RestController
    public class SendMessageController {
        @Autowired
        RabbitTemplate rabbitTemplate;
    
        @GetMapping("/sendDirectMessage")
        public String sendDirectMessage() {
            String messageId = String.valueOf(UUID.randomUUID());
            String messageData = "test message, hello!";
            String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            Map<String,Object> map=new HashMap<>();
            map.put("messageId",messageId);
            map.put("messageData",messageData);
            map.put("createTime",createTime);
            //将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
            rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", map);
            return "ok";
        }
    
    }
    

    启动项目,访问该接口,就能在RabbitMQ的可视化界面可以看到该队列已经存在。

    RabbitMQ消费者:

    一样的先导入依赖:

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

    配置application.properties配置文件

    server.port=8081
    #对于rabbitMQ的支持
    spring.rabbitmq.host=192.168.202.231
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=oilchem
    spring.rabbitmq.password=PoHF*fn%
    #项目的名称
    spring.application.name=rabbitmq-consumer
    

    这时候其实消费者不需要再写配置类了,直接写相关业务

    @Component
    @RabbitListener(queues = "TestDirectQueue1111")
    public class DirectReceiver {
    
        @RabbitHandler
        public void process(Map testMessage){
            System.out.println("DirectReceiver消费者接收的消息为"+testMessage);
        }
    }
    

    这时候启动消息消费者就能取到指定队列中的消息了

    这样就实现了一个最简单的Springboot整合RabbitMQ的案例了。

  • 相关阅读:
    maven打包
    Description Resource Path Location Type Project configuration is not up-to-d
    GoldenGate
    maven打包 把要的依赖也打进去 配置
    mysql如何优化where子句
    根据状态计算操作状态
    kafka direct模式
    Kafka Connect
    Kafka Streams
    如何看源码
  • 原文地址:https://www.cnblogs.com/xiaopanjava/p/14476429.html
Copyright © 2020-2023  润新知