RabbitMQ快速入门

目录

初识MQ

同步调用

异步调用

什么是MQ

RabbitMQ介绍

RabbitMQ的部署指南

RabbitMQ的结构和概念

消息模型

HelloWorld


初识MQ

同步调用

在实际生产中,比如微服务间基于Feign的调用就是属于同步方式,虽然同步调用的时效性比较强,可以立即得到结果,但是会存在一些问题。

  • 耦合度较高,如果不断地需要去对支付系统做功能的增加,比如增加短信服务,就需要不断地去对支付服务源码进行修改
  • 性能、吞吐量较低 ,支付业务在调用订单服务时是同步调用,所以必须得等订单服务完成才能调用仓储服务,然后等仓储服务调用完再调短信服务,总耗时很长
  • 资源浪费,在调用其他服务执行的过程中,支付服务的cpu等资源一直空闲着,资源利用不充分
  • 级联失败问题,比如仓储服务挂掉了,然后支付服务去调用仓储服务就会阻塞

 

异步调用

异步调用最常见的实现就是事件驱动模式

Broker:事件代理者,一旦支付完成,Broker会通知订阅者服务

支付服务只需要让Broker去通知其他服务,不需要等待订阅者服务调用

优势:

  • 服务解耦合:新增功能服务只需要给Broker新增订阅,删除服务只需要取消订阅,不需要修改源码
  • 性能 ,吞吐量提高:不存在调用,所以支付服务不需要等待订阅服务,耗时更短
  • 故障隔离:服务没有强依赖,不用担心级联失败
  • 流量削峰:高并发流量时,通过Broker进行缓存,微服务可以根据自己的能力去Broker获取事件

缺点:

  • 依赖于Broker的可靠性、安全性、吞吐能力
  • 架构复杂了,业务没有明显的流程线,不好追踪管理

 

什么是MQ

MQ(MessaqeQueue),中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。

比较常用的MQ:

Kafka:吞吐能力见长,稳定性比较差,所以更适合于海量数据的传输,但是对于数据安全要求不高的 ,比如说日志数据传输

RubbitMQ和RocketMQ:可靠性更强,稳定性更高,而且吞吐量也不是特别的差,更适合用于对稳定性要求较高的,比如说业务之间的通信


 

RabbitMQ介绍

RabbitMO是基于Erlang语言开发的开源消息通信中间件,官网地址: RabbitMQ: easy to use, flexible messaging and streaming — RabbitMQ

RabbitMQ的部署指南

1.下载镜像

方式一:在线拉取

docker pull rabbitmq:3-management

方式二:从本地加载

上传到虚拟机后,使用命令加载镜像即可:

docker load -i mq.tar

2.安装MQ

docker run \
 -e RABBITMQ_DEFAULT_USER=zstc \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

然后就可以通过主机地址:端口号进入mq管理页面


 

RabbitMQ的结构和概念

发布者将消息发到交换机上,由交换机进行路由发送到队列上,然后再由订阅者去队列上取消息

VirtualHost,虚拟主机:每创建一个用户,都会有自己的虚拟主机,各个虚拟主机之间是相互隔离的,避免干扰


消息模型

基本消息队列和工作消息队列都是基于队列进行消息发送的,没有交换机进行路由,不是一个完整的消息驱动模型

发布订阅模型又按照交换机的类型进行划分为3种:广播,路由,主题


HelloWorld

官方的Helloworld是基于最基础的消息队列模型来实现的,只包括三个角色

  • publisher:消息发布者,将消息发送到队列queue
  • queue:消息队列,负责接受并缓存消息
  • consumer:订阅队列,处理队列中的消息

queue是由mq来管理的,而Publisher和consumer是由我们自己编写的

RabbitMQ的消费者一旦拿到消息,消息就会从消息队列删除

基本消息队列的消息发送流程:

1.建立connection

2.创建channel

3.利用channel声明队列

4.利用channel向队列发送消息

基本消息队列的消息接收流程:

1.建立connection

2.创建channel

3.利用channel声明队列

4.定义consumer的消费行为handleDelivery()5.利用channel将消费者与队列绑定

消费者和生产者都需要声明队列,为了应对消费者先于生产者进入队列的情况

public class PublisherTest {
    @Test
    public void testSendMessage() throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("192.168.150.101");
        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();

    }
public class ConsumerTest {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("192.168.150.101");
        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("等待接收消息。。。。");
    }
}

这种方式代码太过繁琐,所以我们推荐使用SpringAMQP,详情可以看我们下一篇的SpringAMQP笔记

学习笔记from黑马程序员 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值