JAVA03_21学习总结(RabbitMQ消息队列)

今日内容

1. RabbitMQ 消息队列

Rabbitmq 消息队列
    基于AMQP协议的消息队列
    就是将本来一次性完成的,耗时的,需要等待的操作分离出来
        -形成一个单独的模块,就是消息队列
        -例子:
            普通方式:
                A要寄信给B->A要去邮局-要等待接待-要填写具体信息-要每天去邮局查看
            消息队列:
                A把信和具体信息给C-C去寄信-A等待查看结果即可
        -目的:
            减少中间流程的操作时间,为了更加快捷方便

2. RabbitMQ 应用场景

Rabbitmq 应用场景
    1) 异步处理
        串行方式:
            一步一步执行流程,耗时点多,不便捷
        并行方式:
            同时执行多个流程,耗时点略多,非常不便捷
        使用消息队列:
            讲整个模块交给消息队列处理,没有耗时,非常便捷--类似于面向对象
    2)应用解耦
        将两个本来绑在一起的模块解绑,各自运行各自的,互不干扰
        -举例:
            订单系统和库存系统
                一般来说,下订单然后查库存,根据库存结果来判断订单是否成功
                    -耦合性高
                使用消息队列,将订单和库存分开,订单进来后通过消息队列发消息给库存系统,然后订单系统直接返回订单结果即可
                通过消息队列,库存系统在完成是否有库存的结果
                    -完成两个系统的解耦
    3)流量削峰
        在流量比较大的场景中,例如秒杀,抢购中,因为流量过大,经常会造成应用崩溃,所以在秒杀前将所有信息全部进入消息队列,经过消息队列的缓冲,在进入应用执行,超出部分另作打算
    4)日志处理
        每次进行操作时都要记录日志,就会造成日志的大量写入,从而造成数据库压力,所以将日志写进消息队列,在做后续处理,减少压力,提高效率

3. RabbitMQ-helloworld

Rabbitmq用法的一种:
    一个生产者(发送消息)-一个队列-一个消费者(接收消息)
    发送流程
        1)建立连接--对消息队列rabbitmq的链接
            创建连接工厂
            设置连接的参数
                url:主机地址
                username:连接用户名
                password:连接密码
                port:链接端口号
            从工厂中获取一个链接
        2)建立信道
            通过获取的连接建立信道
            通过信道设置交换机和队列的信息--当没有设置的队列时,创建一个该设置的队列
                队列的名称
                是否持久化
                是否独享/排外的
                是否自动删除--消费者接收信息后消息队列自动去除消息
                额外属性--最大存储量...
        3)通过信道发送到交换机,队列
            创建要发送的内容
            发送参数设置
                交换机名称
                若交换机无,填写队列名称
                若交换机有,填写路由键--约束条件
                额外属性设置
                消息
    接收流程
        1)2)相同
        3)监听队列
package com.szr.producer;
​
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
​
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;
​
/**
 * 生产者发送消息
 */
public class Producer {
    //声明消息队列名称-被final修饰
    private static final String QUEUE_NAME = "hello-szr" ;
​
    /**
     * 利用main方法模拟发送消息
     * @param args
     */
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.建立连接-创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接参数
        connectionFactory.setHost("10.35.164.33");//建立主机连接地址
        connectionFactory.setUsername("guest");//连接队列用户名
        connectionFactory.setPassword("guest");//连接队列密码
        connectionFactory.setVirtualHost("/");//连接主机名称
        connectionFactory.setPort(5672);//连接端口号
        //2.建立信道-从工厂中获取一个连接
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //使用信道设置交换机和队列
        channel.queueDeclare(
                QUEUE_NAME,//队列名称
                true,//是否持久化
                false,//是否独享/排外
                true,//是否自动删除
                null//额外属性
        );
        //3)通过信道发送-创建信息
        String message = "这是我的第一个消息队列" ;
        channel.basicPublish(
                "",//没有交换机名称
                QUEUE_NAME,//没有交换机名称,所以填写队列名称
                null,//没有交换机名称,所以没有约定
                message.getBytes(StandardCharsets.UTF_8)//消息
        );
    }
}

JAVA03_21学习总结(RabbitMQ消息队列)_第1张图片

 

package com.szr.consumer;
​
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
​
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;
​
/**
 * 消费者接收消息
 */
public class Consumer {
    //声明消息队列名称-被final修饰
    private static final String QUEUE_NAME = "hello-szr" ;
​
    /**
     * 利用main方法模拟接收消息
     * @param args
     */
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.建立连接-创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接参数
        connectionFactory.setHost("10.35.164.33");//建立主机连接地址
        connectionFactory.setUsername("guest");//连接队列用户名
        connectionFactory.setPassword("guest");//连接队列密码
        connectionFactory.setVirtualHost("/");//连接主机名称
        connectionFactory.setPort(5672);//连接端口号
        //2.建立信道-从工厂中获取一个连接
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //使用信道设置交换机和队列
        channel.queueDeclare(
                QUEUE_NAME,//队列名称
                true,//是否持久化
                false,//是否独享/排外
                true,//是否自动删除
                null//额外属性
        );
        //3.监听队列
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            //1.consumerTag当前的消费的唯一标识。2.delivery 消息本身
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received :  " + message);
        };
        //信道接收
        channel.basicConsume(
                QUEUE_NAME,//监听的队列名称
                true,//是否自动确认-没有报异常,自动确认接收,从消息队列中删除
                deliverCallback,//回调方法
                consumerTag -> { }
        );
    }
}

 JAVA03_21学习总结(RabbitMQ消息队列)_第2张图片

 

4. RabbitMQ-Springboot整合

package com.szr.config;
​
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
/**
 * 消息队列配置类
 */
@Configuration
public class RabbitConfig {
​
    /**
     * 将这个对象交给spring管理起来
     * @return
     */
    @Bean
    public Queue queue(){
        //返回得到的队列
        return new Queue(
                "hello-zhongli" //队列名称
        );
    }
}
package com.szr;
​
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
​
/**
 * 测试类
 */
@SpringBootTest
public class sendTest {
​
    //注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate ;
​
    @Test
    public void testSend(){
        rabbitTemplate.convertAndSend(
                "",//交换机为空
                "hello-zhongli",//队列名称
                "你好,钟离!"//发送内容
        );
    }
}
package com.szr.listen;
​
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
​
/**
 * 监听队列类
 */
@Component //将这个类交给spring管理
public class ListenMessage {
​
    @RabbitListener(queues = "hello-zhongli") //代表要监听哪一个队列
    public void listenMessage(String message){
        System.out.println("message = " + message);
    }
}

JAVA03_21学习总结(RabbitMQ消息队列)_第3张图片

 

5. RabbitMQ-WorkQueues 工作队列模式

WorkQueues 工作队列
    一个生产者(发送消息)-一个队列-多个消费者(多个接收消息)
    结论:
        会将每条消息平均的发给每个消费者,并且遵循轮换规则

6. RabbitMQ-Publish-Subscribe 发布订阅模式

RabbitMQ-Publish-Subscribe 发布订阅模式
    一个发送者-一个交换机-多个队列-多个消费者
    没有规则,给全部的队列发送了内容

7. RabbitMQ-Routing 路由模式

RabbitMQ-Routing 路由模式
    一个发送者-一个交换机,拥有绑定规则-多个队列-多个消费者
    好,但是太麻烦,于是有了通配符

8. RabbitMQ-Topics 通配符模式

RabbitMQ-Topics 通配符模式
    一个发送者-一个交换机,规则加入通配符,更加多样性-多个队列-多个消费者
package com.szr.listen;
​
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
​
/**
 * 监听队列类
 */
@Component //将这个类交给spring管理
public class ListenMessage {
​
    @RabbitListener(queues = "hello-zhongli") //代表要监听哪一个队列
    public void listenMessage(String message){
        System.out.println("message = " + message);
    }
​
    @RabbitListener(queues = "Queue-zhongli")
    public void listenliyueFanout(String message){
        System.out.println("message = " + message);
    }
​
    @RabbitListener(queues = "Queue-leishen")
    public void listendaoqiFanout(String message){
        System.out.println("message = " + message);
    }
​
    @RabbitListener(queues = "Queue-Routing-zhongli")
    public void listenliyueRouting(String message){
        System.out.println("message = " + message);
    }
​
    @RabbitListener(queues = "Queue-Routing-leishen")
    public void listendaoqiRouting(String message){
        System.out.println("message = " + message);
    }
​
    @RabbitListener(queues = "Queue-Topic-zhongli")
    public void listenliyueTopic(String message){
        System.out.println("message = " + message);
    }
​
    @RabbitListener(queues = "Queue-Topic-leishen")
    public void listendaoqiTopic(String message){
        System.out.println("message = " + message);
    }
}
package com.szr.config;
​
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
@Configuration
public class RabbitTopicConfig {
    /**
     * 第一个消息队列,交给spring管理起来,使用@Qualifier来注入
     * @return
     */
    @Bean(name = "Topic-liyue")
    public Queue liyue(){
        return new Queue("Queue-Topic-zhongli");
    }
​
    /**
     * 第二个消息队列,交给spring管理
     * @return
     */
    @Bean(name = "Topic-daoqi")
    public Queue daoqi(){
        return new Queue("Queue-Topic-leishen");
    }
​
    /**
     * 发布订阅模式专门的交换机
     * @return 返回交换机对象
     */
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange("Topic-liyue-daoqi-fanout");
    }
​
    /**
     * 绑定关系,绑定交换机和队列
     * @param queue 通过名称注入的队列-liyue
     * @param topicExchange 只有一个这种类型的交换机
     * @return
     */
    @Bean
    Binding bindTopicLiyueExchange(@Qualifier("Topic-liyue")Queue queue, TopicExchange topicExchange){
        //返回一个声明关系-将注入的队列绑定到交换机上
        return BindingBuilder.bind(queue).to(topicExchange).with("#.liyue");
    }
​
    /**
     * 绑定关系,绑定交换机和队列
     * @param queue 通过名称注入的队列-daoqi
     * @param topicExchange 只有一个这种类型的交换机
     * @return
     */
    @Bean
    Binding bindTopicDaoqiExchange(@Qualifier("Topic-daoqi")Queue queue,TopicExchange topicExchange){
        //返回一个声明关系-将注入的队列绑定到交换机上
        return BindingBuilder.bind(queue).to(topicExchange).with("daoqi.#");
    }
}
package com.szr;
​
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
​
/**
 * 测试类
 */
@SpringBootTest
public class sendTest {
​
    //注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate ;
​
    @Test
    public void testSend(){
        rabbitTemplate.convertAndSend(
                "",//交换机为空
                "hello-zhongli",//队列名称
                "你好,钟离!"//发送内容
        );
    }
​
    @Test
    public void testFanout(){
        rabbitTemplate.convertAndSend(
                "publish-liyue-daoqi-fanout",//交换机名称
                "",//没有约定条件
                "这是庆祝凌华和申鹤复刻"//要发送的消息
        );
    }
​
    @Test
    public void testRouting(){
        rabbitTemplate.convertAndSend(
                "Routing-liyue-daoqi-fanout",//交换机名称
                "liyue",
                "这是庆祝凌华和申鹤复刻"//要发送的消息
        );
    }
​
    @Test
    public void testRouting1(){
        rabbitTemplate.convertAndSend(
                "Routing-liyue-daoqi-fanout",//交换机名称
                "daoqi",
                "这是庆祝凌华和申鹤复刻"//要发送的消息
        );
    }
​
    @Test
    public void testTopic(){
        rabbitTemplate.convertAndSend(
                "Topic-liyue-daoqi-fanout",//交换机名称
                "daoqi.liyue",
                "这是庆祝凌华和申鹤复刻"//要发送的消息
        );
    }
}

你可能感兴趣的:(Java学习--四阶段,java-rabbitmq,rabbitmq,java,学习,开发语言)