RabbitMQ-笔记01

黑马程序员MQ 学习笔记
https://www.rabbitmq.com/
https://www.rabbitmq.com/getstarted.html

1.MQ的基本概念

1.1MQ概述

MQ全称Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。
RabbitMQ-笔记01_第1张图片

1.2MQ优势和劣势

RabbitMQ-笔记01_第2张图片

1.3MQ的优势

1.应用解耦

before
系统容错性差: 当库存系统不可用,导致整个订单系统不可用。
RabbitMQ-笔记01_第3张图片
可维护性差: 新增x系统,需要修改订单系统。
RabbitMQ-笔记01_第4张图片

after: 使用MQ
库存系统不可用,仅影响库存系统自身。
新增x系统无需修改订单系统。
RabbitMQ-笔记01_第5张图片

2.异步提速

before
RabbitMQ-笔记01_第6张图片
after: 使用MQ
RabbitMQ-笔记01_第7张图片

3.削峰填谷

before
RabbitMQ-笔记01_第8张图片
after: 使用MQ
RabbitMQ-笔记01_第9张图片

RabbitMQ-笔记01_第10张图片

1.4 劣势

RabbitMQ-笔记01_第11张图片

小结

RabbitMQ-笔记01_第12张图片

1.5常见MQ产品

RabbitMQ-笔记01_第13张图片

1.6RabbitMQ简介

AMQP协议

RabbitMQ-笔记01_第14张图片

RabbitMQ基础架构

RabbitMQ-笔记01_第15张图片
基本概念
RabbitMQ-笔记01_第16张图片

RabbitMQ工作模式

RabbitMQ-笔记01_第17张图片

1.7JMS(略)

2.RabbiMQ的安装和配置

docker安装

# 5672 : TCP链接的端口 
# 15672 :管理界面端口
[root@s160 ~]# docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management

登录
访问http://IP:15672/#/,RabbitMQ-笔记01_第18张图片

输入用户名密码:guest/guest
RabbitMQ-笔记01_第19张图片

管理控制台使用(略)

3.RabbiMQ快速入门

3.1入门程序

maven依赖

    <dependencies>
      <dependency>
        <groupId>com.rabbitmqgroupId>
        <artifactId>amqp-clientartifactId>
        <version>5.11.0version>
      dependency>
    dependencies>

代码实现

简单消息
不需要使用exchange:
在这里插入图片描述

producer代码实现

  public static void main(String[] args) throws IOException, TimeoutException {
     
        //1. 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        //2. 设置参数
        factory.setHost(HOST);
        factory.setPort(PORT);
        factory.setVirtualHost(VIRTUAL_HOST);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);

        //3. 创建连接 Connection
        Connection connection = factory.newConnection();

        //4. 创建 Channel
        Channel channel = connection.createChannel();

        //5. 创建队列
        /**

         queue – 独立名称
         durable – 是否持久化(重启之后是否存在)
         exclusive – 独占。 只能有一个消费监听队列。
         autoDelete – 是否自动删除,当没有consumer时自动删除
         arguments – 其他配置参数
         */
        channel.queueDeclare("hello_world", true, false, false, null);

        //6. 发送消息
        /**
             exchange – 交换机名称
             routingKey – 路由名称
             props – 配置信息
             body – 发送的消息体
         */
        String body = "hello rabbitmq~~~~";
        //简单模式,不使用exchange ,则routingKey 为topic名称
        channel.basicPublish("", "hello_world", null, body.getBytes() );


        //7.释放连接
        channel.close();
        connection.close();
    }

consumer代码实现

/**

  queue – 队列名称
  autoAck – 自动确认
  consumerTag – a client-generated consumer tag to establish context
  callback – an interface to the consumer object
  */
 channel.basicConsume("hello_world", false,new DefaultConsumer(channel){
     
     @Override
     public void handleDelivery(String consumerTag,
                                Envelope envelope,
                                AMQP.BasicProperties properties,
                                byte[] body)
             throws IOException
     {
     
         System.out.println("consumerTag:"+consumerTag);
         System.out.println("envelope.getExchange:"+envelope.getExchange());
         System.out.println("envelope.getRoutingKey:"+envelope.getRoutingKey());
         System.out.println("properties:"+properties);
         System.out.println("body:"+new String(body));
         System.out.println("---------------------\n");
     }
 });

4.RabbiMQ工作模式

4.1 Work queue工作模式

模式说明
RabbitMQ-笔记01_第20张图片
producer,consumer同 简单模式 **
运行结果: 多个consumer
均匀交替**的消费 消息队列中的消息。
RabbitMQ-笔记01_第21张图片

4.2 Pub/Sub订阅模式-广播(fanout)

模式说明

RabbitMQ-笔记01_第22张图片

producer实现

  public static void main(String[] args) throws IOException, TimeoutException {
     
        //1. 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(HOST);
        factory.setPort(PORT);
        factory.setVirtualHost(VIRTUAL_HOST);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();


        //5. 创建交换机
        /**

         exchange – 交换机名称
         type – 交换机类型:
            DIRECT("direct"),  定向
            FANOUT("fanout"),  广播
            TOPIC("topic"),    通配符
            HEADERS("headers"); 通过参数匹配
         durable – 是否持久化
         autoDelete – 是否自动删除
         internal - 内部使用一般为false
         arguments – 参数
         */
        String exchange = "test_fanout";
        channel.exchangeDeclare(exchange, FANOUT, true, false, false, null);

        //6. 创建队列
        String queue1Name = "test_fanout_queue1";
        String queue2Name = "test_fanout_queue2";
        channel.queueDeclare(queue1Name, true, false, false, null);
        channel.queueDeclare(queue2Name, true, false, false, null);

        //7.绑定队列和交换机
        /**

         queue – 队列名称
         exchange –  队列绑定至 exchange名称
         routingKey –  路由key
         */
        channel.queueBind(queue1Name, exchange,"");
        channel.queueBind(queue2Name, exchange,"");

        //8. 发送消息
        String body = "日志信息:张三调用了findAll方法...日志级别为:info";
        //简单模式,不使用exchange ,则routingKey 为topic名称
        try {
     
            channel.basicPublish(exchange, "", null, body.getBytes() );
        } catch (IOException e) {
     
            e.printStackTrace();
        }

        //7.释放连接
        channel.close();
        connection.close();
    }
结果

exchange
RabbitMQ-笔记01_第23张图片
queue
将消息发送给多个队列中。
在这里插入图片描述

4.3 Routing路由模式(direct)

模式说明

RabbitMQ-笔记01_第24张图片

producer实现

public static void main(String[] args) throws IOException, TimeoutException {
     
        Connection connection = createConnection();
        Channel channel = connection.createChannel();

        String exchange = "test_direct";
        //这里的模式是: DIRECT模式
        channel.exchangeDeclare(exchange, DIRECT, true, false, false, null);

        //6. 创建队列
        String queue1Name = "test_direct_queue1";
        String queue2Name = "test_direct_queue2";
        channel.queueDeclare(queue1Name, true, false, false, null);
        channel.queueDeclare(queue2Name, true, false, false, null);

        //7.绑定队列和交换机
        /**

         queue – 队列名称
         exchange –  队列绑定至 exchange名称
         routingKey –  路由key
         */
        channel.queueBind(queue1Name, exchange,"error");
        channel.queueBind(queue2Name, exchange,"info");
        channel.queueBind(queue2Name, exchange,"error");
        channel.queueBind(queue2Name, exchange,"warning");

        //8. 发送消息
        String body = "日志信息:张三调用了findAll方法...日志级别为:info";
        //简单模式,不使用exchange ,则routingKey 为topic名称
        try {
     
            channel.basicPublish(exchange, "info", null, body.getBytes() );
        } catch (IOException e) {
     
            e.printStackTrace();
        }

        //7.释放连接
        channel.close();
        connection.close();
    }
结果

exchange
RabbitMQ-笔记01_第25张图片

queue
RabbitMQ-笔记01_第26张图片

4.4 Topic 通配符模式

模式说明

RabbitMQ-笔记01_第27张图片
通配符

  • * :代表一个单词
  • #: 代表0或者多个单词

RabbitMQ-笔记01_第28张图片

producer实现

   public static void main(String[] args) throws IOException, TimeoutException {
     
        Connection connection = createConnection();
        Channel channel = connection.createChannel();

        String exchange = "test_topic";
        //这里的模式是: DIRECT模式
        channel.exchangeDeclare(exchange, TOPIC, true, false, false, null);

        //6. 创建队列
        String queue1Name = "test_topic_queue1";
        String queue2Name = "test_topic_queue2";
        channel.queueDeclare(queue1Name, true, false, false, null);
        channel.queueDeclare(queue2Name, true, false, false, null);

        //7.绑定队列和交换机
        //routing_key:   
        channel.queueBind(queue1Name, exchange,"#.error");
        channel.queueBind(queue1Name, exchange,"order.*");
        channel.queueBind(queue2Name, exchange,"*.*");
  

        //8. 发送消息
        String body = "日志信息:张三调用了findAll方法...日志级别为:info";
        //简单模式,不使用exchange ,则routingKey 为topic名称
        try {
     
            //该消息会被 "order.*"和*.* 匹配到, 所以会被queue1Name,queue2Name匹配到
            channel.basicPublish(exchange, "order.info", null, body.getBytes() );
        } catch (IOException e) {
     
            e.printStackTrace();
        }

        //7.释放连接
        channel.close();
        connection.close();
    }

结果

exchange
RabbitMQ-笔记01_第29张图片
topic
RabbitMQ-笔记01_第30张图片



Spring整合RabbitMQ

Spring 整合producer

maven依赖

 <dependencies>
      <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-contextartifactId>
        <version>5.1.7.RELEASEversion>
      dependency>

      <dependency>
        <groupId>org.springframework.amqpgroupId>
        <artifactId>spring-rabbitartifactId>
        <version>2.3.2version>
      dependency>


      <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
      dependency>

      <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-testartifactId>
        <version>5.1.7.RELEASEversion>
      dependency>
    dependencies>

配置信息

rabbitmq.properties

rabbitmq.host=xxx
rabbitmq.port=5672
rabbitmq.username=heima
rabbitmq.password=heima
rabbitmq.virtual-host=/itcast

spring-rabbitmq-producer.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/rabbit
       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
    <context:property-placeholder location="classpath:rabbitmq.properties"/>

    
    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
                               port="${rabbitmq.port}"
                               username="${rabbitmq.username}"
                               password="${rabbitmq.password}"
                               virtual-host="${rabbitmq.virtual-host}"/>
    <rabbit:admin connection-factory="connectionFactory"/>

    
    

    <rabbit:queue id="spring_queue" name="spring_queue" auto-declare="true" />
  
    <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
beans>

测试用例-无exchange

producer

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml")
public class ProducerSpringTest {
     

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testHelloWorld(){
     
        //不指定exchange, routingKey即为 queue名称
        rabbitTemplate.convertAndSend("spring_queue","hello world spring...");
    }
}

结果
在这里插入图片描述

测试用例-广播

exchange配置

   <rabbit:queue id="spring_fanout_queue_1" name="spring_fanout_queue_1" auto-declare="true"/>
   <rabbit:queue id="spring_fanout_queue_2" name="spring_fanout_queue_2" auto-declare="true"/>

    
    <rabbit:fanout-exchange id="spring_fanout_exchange" name="spring_fanout_exchange" auto-declare="true">
        <rabbit:bindings>
            <rabbit:binding queue="spring_fanout_queue_1"/>
            <rabbit:binding queue="spring_fanout_queue_2"/>
        rabbit:bindings>
    rabbit:fanout-exchange>

producer-广播


    @Test
    public void testFanout(){
     
        //不指定exchange, routingKey即为 queue名称
        rabbitTemplate.convertAndSend("spring_fanout_exchange",""," spring fanout...");
    }

exchange
RabbitMQ-笔记01_第31张图片

queue
在这里插入图片描述

测试用例-direct(略)

exchange配置

    
    <rabbit:direct-exchange id="spring_direct_exchange" name="spring_direct_exchange" auto-declare="true">
        <rabbit:bindings>
            
            <rabbit:binding queue="spring_queue" key="xx"/>
        rabbit:bindings>
    rabbit:direct-exchange>

测试用例-topic通配符

exchange配置

    <rabbit:queue id="spring_topic_queue_star" name="spring_topic_queue_star" auto-declare="true"/>
    <rabbit:queue id="spring_topic_queue_well" name="spring_topic_queue_well" auto-declare="true"/>
    <rabbit:queue id="spring_topic_queue_well2" name="spring_topic_queue_well2" auto-declare="true"/>
    
    <rabbit:topic-exchange id="spring_topic_exchange" name="spring_topic_exchange" auto-declare="true">
        <rabbit:bindings>
            <rabbit:binding pattern="heima.*" queue="spring_topic_queue_star"/>
            <rabbit:binding pattern="heima.#" queue="spring_topic_queue_well"/>
            <rabbit:binding pattern="itcast.#" queue="spring_topic_queue_well2"/>
        rabbit:bindings>
    rabbit:topic-exchange>

producer-通配符


    @Test
    public void testTopic(){
     
        //不指定exchange, routingKey即为 queue名称
        rabbitTemplate.convertAndSend("spring_topic_exchange","itcast.nihao"," spring topic: itcast.nihao...");
    }

exchange
RabbitMQ-笔记01_第32张图片

queue
在这里插入图片描述

Sprng整合consumer

maven依赖

同生产者(略)

配置信息

rabbitmq.properties

rabbitmq.host=xxx
rabbitmq.port=5672
rabbitmq.username=heima
rabbitmq.password=heima
rabbitmq.virtual-host=/itcast

spring-rabbitmq-consumer.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/rabbit
       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
    
    <context:property-placeholder location="classpath:rabbitmq.properties"/>

    
    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
                               port="${rabbitmq.port}"
                               username="${rabbitmq.username}"
                               password="${rabbitmq.password}"
                               virtual-host="${rabbitmq.virtual-host}"/>

    <bean id="springQueueListener" class="cn.jhs.mq.consumer.listener.SpringQueueListener"/>

    <rabbit:listener-container connection-factory="connectionFactory" auto-declare="true">
    	        

        <rabbit:listener ref="springQueueListener" queue-names="spring_queue"/>
    rabbit:listener-container>
beans>

测试用例

自定义MessageListener

public class SpringQueueListener implements MessageListener {
     
    @Override
    public void onMessage(Message message) {
     
        System.out.println(new String(message.getBody()));
    }
}

consumer.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-rabbitmq-consumer.xml")
public class ConsumerSpringTest {
     

    @Test
    public void test1(){
     
        while(true){
     
        }
    }
}


SpringBoot整合RabbitMQ(略)

生产者

maven依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starterartifactId>
    dependency>


    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-amqpartifactId>
    dependency>

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>

配置信息

application.yaml

spring:
  rabbitmq:
    host: xxx
    port: 5672
    username: heima
    password: heima
    virtual-host: /itcast

配置configuration

@Configuration
public class RabbitMQConfig {
     

    public static final String EXCHANGE_NAME = "boot_topic_exchange";
    public static final String QUEUE_NAME1 = "boot_queue1";
    public static final String QUEUE_NAME2 = "boot_queue2";
    public static final String ROUTING_KEY = "boot.*";

    //1.交换机
    @Bean("bootExchange")
    public Exchange bootExchange(){
     
        return ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(true).build();
    }

    //2. 队列
    @Bean("bootQueue1")
    public Queue bootQueue1(){
     
        return QueueBuilder.durable(QUEUE_NAME1).build();
    }

    @Bean("bootQueue2")
    public Queue bootQueue2(){
     
        return QueueBuilder.durable(QUEUE_NAME2).build();
    }

    /**
     * 3. 绑定队列和交换机的关系 Binding
     *  - 知道那个队列
     *  - 知道那个交换机
     *  - routing key
     */
    @Bean( "bindQueueExchange1")
    public Binding bindQueueExchange(@Qualifier("bootQueue1") Queue queue, @Qualifier("bootExchange") Exchange exchange) {
     
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY).noargs();
    }

    @Bean( "bindQueueExchange2")
    public Binding bindQueueExchange2(@Qualifier("bootQueue2") Queue queue2, @Qualifier("bootExchange") Exchange exchange) {
     
        return BindingBuilder.bind(queue2).to(exchange).with(ROUTING_KEY).noargs();
    }
}

测试-发送消息

@SpringBootTest(classes = SpringbootRabbitApplication.class)
public class ProducerTest {
     
	
	//注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSend(){
     
        String exchangeName = "boot_topic_exchange";
        String routingKey = "boot.haha";
        String msg = "boot mq hello";
        rabbitTemplate.convertAndSend(exchangeName,routingKey, msg);
    }
}

测试结果

exchange
RabbitMQ-笔记01_第33张图片
queue
RabbitMQ-笔记01_第34张图片

消费者

maven依赖(同provider)

配置RabbitListener

@Component
public class RabbitMQListener {
     

    @RabbitListener(queues = {
     "boot_queue1","boot_queue2"})
    public void listenerQueue(Message message){
     
        System.out.println(message);
    }
}

测试结果

(Body:'boot mq hello' MessageProperties [headers={}, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=boot_topic_exchange, receivedRoutingKey=boot.haha, deliveryTag=1, consumerTag=amq.ctag-zedDxckfNB93PmweTnq-SA, consumerQueue=boot_queue1])
(Body:'boot mq hello' MessageProperties [headers={}, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=boot_topic_exchange, receivedRoutingKey=boot.haha, deliveryTag=2, consumerTag=amq.ctag-Vq8EGDzeKUiWEW5sHeVeYA, consumerQueue=boot_queue2])

你可能感兴趣的:(MQ,rabbitmq)