【RabbitMQ】 相关概念 + 工作模式

本文将介绍一些MQ中常见的概念,同时也会简单实现一下RabbitMQ的工作流程。

MQ概念

Message Queue消息队列。是用来存储消息的队列,多用于分布式系统之间的通信。

系统间调用通常有:同步通信和异步通信。MQ就是在异步通信的时候使用的。

同步通信:

异步通信:

MQ作用

  • 异步解耦:在业务流程中,一些操作可能非常耗时,但并不需要即时返回结果。可以借助消息队列(MQ)将这些操作异步化。例如,当用户注册后,可以将发送注册短信或邮件通知作为异步任务处理,而不必等待这些操作完成后才告知用户注册成功。
  • 流量削峰:在访问量剧增的情况下,应用仍然需要继续发挥作用,但这样的突发流量并不常见。如果以能处理这类峰值为标准而投入资源,必然是巨大的浪费。使用MQ可以使关键组件支撑突发访问压力,不会因为突发流量而崩溃。例如,秒杀或促销活动中,可以使用MQ来控制流量,将请求排队,系统根据自己的处理能力逐步处理这些请求。
  • 消息分发:当多个系统需要对同一数据做出响应时,可以使用MQ进行消息分发。例如,支付成功后,支付系统可以向MQ发送消息,其他系统订阅该消息,而无需轮询数据库。
  • 延迟通知:在需要在特定时间后发送通知的场景中,可以使用MQ的延迟消息功能。例如,在电子商务平台中,如果用户下单后一定时间内未支付,可以使用延迟队列在超时后自动取消订单。

AMQP

AMQP(Advanced Message Queuing Protocol)是一个高级消息队列协议,定义了一系列消息交换功能,包括交换器(Exchange)和队列(Queue)。这些组件共同工作,使得生产者可以将消息发送到交换器,由队列接收并等待消费者取走。AMQP还定义了一个网络协议,允许客户端应用通过该协议与消息代理和AMQP模型进行交互通信。RabbitMQ遵循AMQP协议,使用Erlang实现,并支持其他协议如STOMP和MQTT。可以说AMQP模型和RabbitMQ模型结构一致。


RabbitMQ

功能完备: MQ 功能较为全面,几乎支持所有主流语言。
开源友好: 界面非常友好,易于使用。
性能: 性能良好,吞吐量可达到万级。
社区活跃度: 社区活跃度较高。
适用场景: 适合中小型公司,数据量和并发量较小的场景


Producer和Consumer

Producer(生产者):是RabbitMQ Server的客户端,向RabbitMQ发送消息。消息通常带有业务逻辑结构的数据,例如JSON字符串,并可能包含标签,RabbitMQ根据标签路由消息。

Consumer(消费者):也是RabbitMQ Server的客户端,从RabbitMQ接收消息。在消费过程中,标签会被丢弃,消费者只收到消息,且无需知道消息的生产者。

Broker(消息代理):即RabbitMQ Server,负责接收和收发消息。通常,一个RabbitMQ Broker可以视为一个RabbitMQ服务节点或实例,大多数情况下等同于一台RabbitMQ服务器。


Connection和Channel

Connection(连接):是客户端与RabbitMQ服务器之间的TCP连接。这是建立消息传递的基础,负责传输客户端和服务器之间的所有数据和控制信息。

Channel(通道/信道):是在Connection之上的一个抽象层。在RabbitMQ中,一个TCP连接可以有多个Channel,每个Channel都是独立的虚拟连接。消息的发送和接收都是基于Channel进行的。通道的主要作用是将消息的读写操作复用到同一个TCP连接上,从而减少建立和关闭连接的开销,提高性能


Virtual host

Virtual Host(虚拟主机):这是一个虚拟概念,为消息队列提供逻辑上的隔离机制。在RabbitMQ中,一个Broker Server上可以存在多个Virtual Host。它允许不同的用户在同一RabbitMQ服务器上创建和管理独立的交换机(exchange)、队列(queue)等,类似于MySQL中的数据库(database)。


Queue

Queue: 队列, 是RabbitMQ的内部对象, 用于存储消息。


Exchange

Exchange(交换机):是消息到达RabbitMQ Broker的第一站。它负责接收生产者发送的消息,并根据特定的规则将这些消息路由到一个或多个队列(Queue)中。Exchange的主要作用是消息路由,它根据类型和规则决定如何转发接收到的消息。

交换机类型

RabbitMQ中的交换机有四种主要类型,每种类型有不同的路由策略:

  1. Fanout:将消息广播到所有绑定到该交换机的队列,无视路由键。
  2. Direct:根据消息的路由键将消息精确路由到与交换机绑定的队列。
  3. Topic:使用通配符模式匹配路由键,将消息路由到匹配的队列。
  4. Headers:基于消息头部的属性进行路由,路由键不会被使用。(很少使用)

AMQP协议中还有另外两种交换机类型:

System:用于内部系统交换和管理,不用于常规的消息路由。
自定义(Custom):用户可以定义自己的交换机类型,以满足特定的需求。

根据交换机类型的不同,创建了许多不同的工作模式。

Routing Key(路由键)
定义: 路由键是一个字符串,通过它生产者在将消息发送到交换器时告诉交换器如何处理该消息。
作用: 决定了消息的路由路径,即消息应发送到哪个队列或哪些队列。
Binding Key(绑定键)
定义: 在 RabbitMQ 中,通过 Binding(绑定)将交换器与队列关联时,通常会指定一个 Binding Key。
作用: 引导 RabbitMQ 知道如何将消息路由到相应的队列。这个键通常与路由键相关联,从而实现消息的过滤和分发。

通常来说路由键和绑定键没什么区别


工作流程

Producer(生产者) 产生了一条消息。
Producer 连接到 RabbitMQ Broker,建立一个连接(Connection),并开启一个信道(Channel)。
Producer 声明一个交换机(Exchange),用于路由消息。
Producer 声明一个队列(Queue),用于存放消息。
Producer 发送消息至 RabbitMQ Broker。
RabbitMQ Broker 接收消息,并将其存入相应的队列(Queue)中。如果未找到相应的队列,则根据生产者的配置,选择丢弃或退回消息给生产者。


工作模式

RabbitMQ提供了七个工作模式。查看文档即可:RabbitMQ Tutorials | RabbitMQ

工作模式图中的字母:

P(生产者):也就是要发送消息的程序。

C(消费者):消费者,消息的接收者。

Queue(消息队列):缓存消息;生产者将消息投递到其中,消费者从中取出消息。

Exchange(交换机X):按照规则分发消息。

相关通用代码提取到Constants类中

public class Constants {
    // 主机ip
    public static final String HOST = "ip地址";
    // rabbitmq服务器端口号 默认是5672
    public static final int PORT = 5672;
    // rabbitmq用户名
    public static final String USER_NAME = "用户名";
    // rabbitmq用户密码
    public static final String PASSWORD = "用户密码";
    // rabbitmq虚拟主机
    public static final String VIRTUAL_HOST = "虚拟主机名";

    // 简单模式
    public static final String SIMPLE_QUEUE = "simple.queue";

    // 工作队列模式
    public static final String WORK_QUEUE = "work.queue";

    // 发布订阅模式
    public static final String FANOUT_EXCHANGE = "fanout.exchange";
    public static final String FANOUT_QUEUE1 = "fanout.queue1";
    public static final String FANOUT_QUEUE2 = "fanout.queue2";

    // 路由模式
    public static final String DIRECT_EXCHANGE = "direct.exchange";
    public static final String DIRECT_QUEUE1 = "direct.queue1";
    public static final String DIRECT_QUEUE2 = "direct.queue2";

    // 通配符模式
    public static final String TOPIC_EXCHANGE = "topic.exchange";
    public static final String TOPIC_QUEUE1 = "topic_queue1";
    public static final String TOPIC_QUEUE2 = "topic_queue2";

    // rpc 模式
    public static final String RPC_REQUEST_QUEUE = "rpc.request.queue";
    public static final String RPC_RESPONSE_QUEUE = "rpc.response.queue";

    // publisher confirms
    public static final String PUBLISHER_CONFIRMS_QUEUE1 = "publisher.confirms.queue1";
    public static final String PUBLISHER_CONFIRMS_QUEUE2 = "publisher.confirms.queue2";
    public static final String PUBLISHER_CONFIRMS_QUEUE3 = "publisher.confirms.queue3";

    // 推拉模式
    public static final String MESSAGE_QUEUE = "message.queue";
}

简单模式

特点: 一个生产者 P 和一个消费者 C,消息只能被消费一次。这种模式也称为点对点(Point-to-Point)模式。

适用场景: 当消息只能被单个消费者处理时。


生产者代码

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import rabbitmq.common.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1. 创建链接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(Constants.HOST);
        factory.setPort(Constants.PORT);
        factory.setUsername(Constants.USER_NAME);
        factory.setPassword(Constants.PASSWORD);
        factory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = factory.newConnection();

        // 2. 开启信道
        Channel channel = connection.createChannel();
        // 3. 声明交换机 简单模式使用内置交换机 所以不用声明

        // 4. 声明队列
        /*
         * queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
         *                                  Map<String, Object> arguments)
         *  参数说明:
         *  queue: 队列名称
         *  durable: 可持久化
         *  exclusive: 是否独占
         *  autoDelete: 是否自动删除
         *  arg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值