• 微服务07-认识MQ+RabbitMQ入门


    1.前言

    了解同步调用和异步调用

    在这里插入图片描述

    1.1.同步调用

    比如这里的支付服务,需要等待订单服务、短信服务…执行完毕才能执行,这样支付整个流程完毕需要500ms

    然后如果订单、仓储等其中一个服务挂掉了,那么支付服务请求请求不了,挂掉的服务越来越多,级联失败;——>服务提供者出现问题,那么整个微服务都会出现故障;

    资源浪费:消费者需要等待服务提供者响应,不能干其他事情只能干等;

    耦合度较高:每次加入新的需求,还需要动原来的代码——>比如:订单加了一个用户积分,那么Feign模块中还要加相关代码,以便订单模块调用,订单模块还需要+调用用户积分的代码:需要改动订单代码;

    再来一个场景:比如说,我们要删除某个业务,需要将支付服务中的调用某个业务的相关代码删除;

    缺点

    在这里插入图片描述
    在这里插入图片描述

    1.2.异步调用

    利用了一个Broker进行事件通知

    优点

    级联失败问题得到解决:比如订单服务挂了,它并不会影响支付服务,自己重启就行了
    耦合度低:因为支付服务不需要调用其他服务了,而是通过发布事件,Broker对其他事务进行通知,你支付服务该干嘛干嘛,发布完消息返回用户支付成功——>支付服务发布支付成功消息给到Broker,然后Broker进行通知——>对其他服务,然后其他服务执行即可;

    吞吐量提升:因为不存在服务之间的调用,所以时间较少(发布信息),能发送的数据就能够越多——>牺牲:消息的延迟,从发送到接收

    流量削峰:Broker作为缓冲,将并发请求保存起来,然后通过微服务里面的实现的功能,对请求进行放行——>从而达到流量削峰的效果

    缺点

    异步调用只是通知你干一件事情,并不知道你干没干完(通过Broker发送请求让你干事情,从而达到解耦的效果)

    在这里插入图片描述
    流量削峰

    Broker作为缓冲区对请求进行缓存;
    在这里插入图片描述
    在这里插入图片描述

    2.认识MQ

    在这里插入图片描述
    RabbitMQ:一般用于业务之间的通信,安全稳定。

    KafKa:一般用于海量数据处理,单机吞吐量高:每秒钟能发送的数据大小来分析

    3.RabbitMQ入门

    3.1 安装使用

    1.导入虚拟机并解压
    在这里插入图片描述

    2.运行镜像产生MQ容器
    在这里插入图片描述

    3.运行成功
    在这里插入图片描述

    4.访问RabbitMQ
    在这里插入图片描述

    5.RabbitMQ各属性解读
    发布者Publisher会把消息->给到交换机(Exchange),交换机路由给到指定的消息队列(Queue),queue把消息保存起来,然后消费者consumer会从queue将消息拿出来

    VirtualHost:各个虚拟主机是不一样的,相当于对操作进行分组——>不同用户访问是不同的虚拟主机,体现隔离性;

    在这里插入图片描述

    3.2 常见消息模型

    在这里插入图片描述

    3.3 简单队列案例

    在这里插入图片描述

    3.3.1 发送

    1.建立消息队列连接

    IDEA中写好配置

    package cn.itcast.mq.helloworld;
     
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import org.junit.Test;
     
    import java.io.IOException;
    import java.util.concurrent.TimeoutException;
     
    public class PublisherTest {
        @Test
        public void testSendMessage() throws IOException, TimeoutException {
            // 1.建立连接
            ConnectionFactory factory = new ConnectionFactory();
            // 1.1.设置连接参数,分别是:主机名、消息通信端口号、vhost、用户名、密码
            factory.setHost("192.168.88.130");
            factory.setPort(5672);
            factory.setVirtualHost("/");
            factory.setUsername("itcast");
            factory.setPassword("123321");
            // 1.2.建立连接
            Connection connection = factory.newConnection();
     
            // 2.创建通道Channel
            Channel channel = connection.createChannel();
     
            // 3.创建队列
            String queueName = "simple.queue";
            channel.queueDeclare(queueName, false, false, false, null);
     
            // 4.发送消息
            String message = "hello, rabbitmq!";
            channel.basicPublish("", queueName, null, message.getBytes());
            System.out.println("发送消息成功:【" + message + "】");
     
            // 5.关闭通道和连接
            channel.close();
            connection.close();
     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    运行代码后

    进入RabbitMQ发现连接成功
    在这里插入图片描述

    2.创建一个通道,以此发送消息到队列
    在这里插入图片描述

    3.利用通道来声明队列
    在这里插入图片描述

    4.发送消息
    在这里插入图片描述

    5.消息成功发送到队列中,消息断开,不管你后面的接收

    3.3.2 接收

    老样子 IDEA中写好配置,运行即能接收

    package cn.itcast.mq.helloworld;
     
    import com.rabbitmq.client.*;
     
    import java.io.IOException;
    import java.util.concurrent.TimeoutException;
     
    public class ConsumerTest {
     
        public static void main(String[] args) throws IOException, TimeoutException {
            // 1.建立连接
            ConnectionFactory factory = new ConnectionFactory();
            // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
            factory.setHost("192.168.88.130");
            factory.setPort(5672);
            factory.setVirtualHost("/");
            factory.setUsername("itcast");
            factory.setPassword("123321");
            // 1.2.建立连接
            Connection connection = factory.newConnection();
     
            // 2.创建通道Channel
            Channel channel = connection.createChannel();
     
            // 3.创建队列
            String queueName = "simple.queue";
            channel.queueDeclare(queueName, false, false, false, null);
     
            // 4.订阅消息
            channel.basicConsume(queueName, true, new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope,
                                           AMQP.BasicProperties properties, byte[] body) throws IOException {
                    // 5.处理消息
                    String message = new String(body);
                    System.out.println("接收到消息:【" + message + "】");
                }
            });
            System.out.println("等待接收消息。。。。");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    跟消息队列的消息发送流程差不多,注意点就是也声明了队列:避免队列不存在

    还有一点:定义了consume消费行为handleDelivery()消费行为和队列名字绑定了,只要一有消息就会传递到队列当中被消费行为执行;——>一个异步操作,消费者与消息提供者互相不等待

    从先执行后面的打印信息,再执行前面的接收到消息可以看出是一个异步操作:接没接受到不管 (两个线程一个回调,一个往后面继续走

    在这里插入图片描述

    消费者收到消息后,RabbitMQ中的消息队列的消息就没有了

    在这里插入图片描述

  • 相关阅读:
    电脑文档数据恢复?别急,一招教你快速找回丢失数据!
    黑客(网络安全)技术自学30天
    [iOS开发]编译过程
    LastPass 开发者系统被黑客窃取源代码
    基于 SpringBoot + MyBatis 的网页版五子棋对战
    Python 越来越火爆
    新手怎么使用GitHub?
    PMP考试有用吗?
    盘点常见的动态内存的错误
    在iframe标签中操作外层dom
  • 原文地址:https://blog.csdn.net/weixin_67201964/article/details/132848451