微服务[学成在线] day05:消息中间件 RabbitMQ

本文详细介绍了RabbitMQ的基础知识和工作原理,包括安装配置、快速入门示例、工作模式(如Work queues、Publish/Subscribe、Routing、Topics、Header和RPC模式)以及Spring Boot整合RabbitMQ的实践。通过实例展示了如何在Java环境中使用RabbitMQ进行消息生产与消费,适合开发者学习微服务架构中消息队列的使用。
摘要由CSDN通过智能技术生成

😎 知识点概览

为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。

本章节为【学成在线】项目的 day05 的内容

  • RabbitMQ 的基本应用场景
  • 使用原生RabbitMQ 库构建生产者与消费者模型
  • 整合 Springboot 实现 RabbitMQ 生产者与消费者模型

目录

内容会比较多,小伙伴们可以根据目录进行按需查阅。

一、需求分析

业务流程如下:

1、管理员进入管理界面点击 “页面发布”,前端请求 cms 页面发布接口。

2、cms 页面发布接口执行页面静态化,并将静态化页面(html文件)存储至GridFS中。

3、静态化成功后,向消息队列发送页面发布的消息。页面发布的最终目标是将页面发布到服务器。通过消息队列将页面发布的消息发送给各个服务器。

4、消息队列负责将消息发送给各各服务器上部署的 Cms Client (Cms客户端)。在服务器上部署 Cms Client(Cms客户端),客户端接收消息队列的通知。

5、每个接收到页面发布消息的 Cms ClientGridFS 获取 Html 页面文件,并将 Html 文件存储在本地服务器。CmsClient 根据页面发布消息的内容请求 GridFS 获取页面文件,存储在本地服务器 。

二、初识RabbitMQ

要实现上边页面发布的功能,有一个重要的环节就是由消息队列将页面发布的消息通知给各各服务器。

本节的教学目标是对MQ的研究:

1、理解MQ的应用场景

2、理解MQ常用的工作模式

0x01 简单的介绍

RabbitMQ 简介

MQ全称为 Message Queue,即消息队列, RabbitMQ是由 erlang 语言开发,基于**AMQP(Advanced Message Queue 高级消息队列协议)**协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。

RabbitMQ官方地址:http://www.rabbitmq.com/

开发中消息队列通常有如下应用场景:

  • 任务异步处理

    将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。

  • 应用程序解耦合

    MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。

  • 市场上还有哪些消息队列?
    ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ、Redis。

  • 为什么使用RabbitMQ呢?

    1、使得简单,功能强大。
    2、基于 AMQP 协议。
    3、社区活跃,文档完善。
    4、高并发性能好,这主要得益于 Erlang 语言。
    5、Spring Boot 默认已集成 RabbitMQ

其它相关知识

AMQP是什么 ?

AMQP 是一套公开的消息队列协议,最早在2003年被提出,它旨在从协议层定义消息通信数据的标准格式,为的就是解决 MQ 市场上协议不统一的问题。RabbitMQ 就是遵循 AMQP 标准协议开发的MQ服务。

JMS是什么 ?

JMSjava 提供的一套消息服务API标准,其目的是为所有的 java 应用程序提供统一的消息通信的标准,类似 javajdbc,只要遵循 jms 标准的应用程序之间都可以进行消息通信。它和 AMQP 有什么 不同,jms 是java语言专属的消息服务标准,它是在api层定义标准,并且只能用于 java 应用;而 AMQP 是在协议层定义的标准,是跨语言的 。

0x02 快速入门

RabbitMQ 的工作原理

下图是 RabbitMQ 的基本结构

组成部分说明如下:

  • Broker:消息队列服务进程,此进程包括两个部分:ExchangeQueue
  • Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过滤。
  • Queue:消息队列,储存消息的队列,消息到达队列并转发给指定的消费方。
  • Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到 MQ
  • Consumer:消息消费者,即消费方客户端,接收 MQ 转发的消息。

消息 发布接收 流程:

-----发送消息-----

1、生产者和 Broker 建立TCP连接。

2、生产者和 Broker 建立通道。

3、生产者通过通道消息发送给 Broker ,由 Exchange 将消息进行转发。

4、Exchange将消息转发到指定的 Queue(队列)

----接收消息-----

1、消费者和 Broker 建立TCP连接

2、消费者和 Broker 建立通道

3、消费者监听指定的 Queue(队列)

4、当有消息到达 QueueBroker 默认将消息推送给消费者。

5、消费者接收到消息。

安装 RabbitMQ

1、下载并安装

RabbitMQ由 Erlang 语言开发,Erlang 语言用于并发及分布式系统的开发,在电信领域应用广泛,OTP(OpenTelecom Platform)作为 Erlang 语言的一部分,包含了很多基于 Erlang 开发的中间件及工具库,安装 RabbitMQ 需要安装 Erlang/OTP,并保持版本匹配,如下图:

本项目使用 Erlang/OTP 20.3 版本和 RabbitMQ3.7.3 版本。

官网 RabbitMQ 的下载地址:http://www.rabbitmq.com/download.html

下载erlang

地址如下:http://erlang.org/download/otp_win64_20.3.exe

erlang安装完成需要配置erlang环境变量: ERLANG_HOME=D:\Program Files\erl9.3 在path中添
加%ERLANG_HOME%\bin;

安装RabbitMQ

下载地址 https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.3

这里要注意 rabbitMQ的安装路径

2、启动

安装成功后会自动创建RabbitMQ服务并且启动。

  1. 在系统path变量中添加 rabbitMQ 的环境变量:D:\[rabbitMQ的安装路径]\sbin;

  2. 添加环境变量后,按下 Win + X 以管理员身份运行powershell 或者 cmd

  3. 运行 rabbitmq-plugins.bat enable rabbitmq_management 命令

    安装过程

  4. 运行 rabbitmq-service.bat stoprabbitmq-service.bat start 重启 rabbitMQ

  5. 启动成功,访问 http://localhost:15672 登录Rabbit MQ,初始账号密码为 guest/guest

3、注意事项

1、安装 erlangrabbitMQ 以管理员身份运行。

2、当卸载重新安装时会出现 RabbitMQ 服务注册失败,此时需要进入注册表清理 erlang
搜索RabbitMQ、ErlSrv,将对应的项全部删除。

Hello World

工作模式

以下过程我们参考官方教程(http://www.rabbitmq.com/getstarted.html)测试hello world:

1、搭建环境
java client

生产者和消费者都属于客户端,rabbitMQ的java客户端如下:

我们先用 rabbitMQ 官方提供的 java client 测试,目的是对 RabbitMQ 的交互过程有个清晰的认识。

参考 :https://github.com/rabbitmq/rabbitmq-java-client/

创建maven工程

创建生产者工程和消费者工程,分别加入RabbitMQ java client的依赖。

test-rabbitmq-producer:生产者工程

test-rabbitmq-consumer:消费者工程

依赖配置如下:

<dependencies>
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>4.0.3</version><!--此版本与spring boot 1.5.9版本匹配-->
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </dependency>
</dependencies>

2、生产者

在生产者工程下的单元测试内创建测试类如下

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

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

public class Producer01 {
   
    //队列名称
    private static final String QUEUE = "helloworld2";

    public static void main(String[] args) throws IOException, TimeoutException {
   
        Connection connection = null;
        Channel channel = null;
        try {
   
            //构建连接工厂,并设置一些基本的链接信息
            ConnectionFactory factory = new ConnectionFactory();

            factory.setHost("localhost");
            factory.setPort(5672);
            factory.setUsername("guest");
            factory.setPassword("guest");
            //rabbitMQ默认的虚拟机名称为“/”,虚拟机相当于一个独立的mq服务
            factory.setVirtualHost("/");

            //创建与RabbitMQ服务的TCP连接
            connection = factory.newConnection();

            //创建与Exchange的通道,每个连接可以创建多个通道,每个通道代表一个会话任务
            channel = connection.createChannel();

            /**
             * 声明队列,如果Rabbit中没有此队列,将自动创建
             * String queue, boolean durable, boolean exclusive, boolean autoDelete,Map<String, Object> arguments
             *
             * param1:队列名称
             * param2:是否持久化
             * param3:队列是否独占此连接
             * param4:队列不再使用时是否自动删除此队列
             * param5:队列参数
             */
            channel.queueDeclare(QUEUE,true,false,false,null);
            String message = "hello world 小明" + System.currentTimeMillis();

            /**
             * 消息发布方法
             消息发布方法
             * param1:Exchange的名称,如果没有指定,则使用Default Exchange
             * param2:routingKey,消息的路由Key,是用于Exchange(交换机)将消息转发到指定的消息队列
             * param3:消息包含的属性
             * param4:消息体
             * 这里没有指定交换机,消息将发送给默认交换机,每个队列也会绑定那个默认的交换机,但是不能显示绑定或解除绑定
             * 默认的交换机,routingKey等于队列名称
             */
            channel.basicPublish("",QUEUE,null,message.getBytes());
            System.out.println("Send Message is: ' " + message + " '");

        }catch ( Exception ex){
   
            ex.printStackTrace();
        }finally {
   
            //先关闭通道,再关闭连接
            if(channel != null){
   
                channel.close();
            }
            if(channel != null){
   
                connection.close();
            }
        }
    }
}

运行生产者后,RabbitMQ 后台会接收到一条等待消费的消息

3、消费者
import com.rabbitmq.client.*;

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

public class Consumer01 {
   
    private static final String QUEUE = "helloworld2";

    public static void main(String[] args) throws IOException, TimeoutException {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        //rabbitMQ默认的虚拟机名称为“/”,虚拟机相当于一个独立的mq服务
        factory.setVirtualHost("/");

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

        //声明队列
        /** 参数:String queue, boolean durable, boolean exclusive, boolean autoDelete,
         Map<String, Object> arguments
         * 参数明细:
         * 1、queue 队列名称
         * 2、durable 是否持久化,如果持久化,mq重启后队列还在
         * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭,队列则自动删除,可用于临时队列的创建
         * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive共同为true,就可以实现临时队列
         * 5、argmuacnts,可以设置一个队列扩展参数,比如:可设置存活的时间
         */
        channel.queueDeclare(QUEUE, true, false, false, null);

        //定义消费方法
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
   
            /**
             * 消费者接收消息调用此方法
             * @param consumerTag 消费者的标签,在channel.basicConsume()去指定
             * @param envelope 消息包的内容,可从中获取消息id,消息routingkey,交换机,消息和重传标志
            (收到消息失败后是否需要重新发送)
             * @param properties 消息属性
             * @param body 消息内容
             * @throws IOException
            1、发送端操作流程
            1)创建连接
            2)创建通道
            3)声明队列
            4)发送消息
            2、接收端
            1)创建连接
            2)创建通道
            3)声明队列
            4)监听队列
            5)接收消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
   
                //交换机
                String exchange = envelope.getExchange();
                //路由key
                String routingKey = envelope.getRoutingKey();
                //消息id
                long deliveryTag = envelope.getDeliveryTag();
                //消息内容
                String msg = new String(body, "utf-8");
                System.out.println("receive message.." + msg);
            }
        };

        /**
         * 监听队列String queue, boolean autoAck,Consumer callback
         * 参数明细
         * 1、queue 队列名称
         * 2、autoAck 是否自动回复,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复会删除消息,设置为false则需要手动回复
         * 3、callback 消费消息的方法,消费者接收到消息后调用此方法
   
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值