Message queue 消息队列--RabbitMQ 【基础入门】

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是平顶山大师,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的博客专栏《Message queue 消息队列--RabbitMQ 【基础入门】》。🎯🎯

🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁

目录

[一,Message queue介绍:](#一,Message queue介绍:)

二,RabbitMQ介绍:

2.1什么是RabbitMQ?

2.2RabbitMQ组成?

2.3RabbitMQ工作原理

2.4RabbitMQ在企业项目中使用场景:

2.5Docker安装部署RabbitMQ

2.6创建springboot项目嵌套RabbitMQ

传递字符串类型

传递实体类型

访问测试:


一,Message queue介绍:

1.1使用消息队列的优点:

服务之间最常见的通信方式是直接调用彼此来通信,消息从一端发出后立即就可以达到另一端,称为即时消息通讯(同步通信) 消息从某一端发出后,首先进入一个容器进行临时存储,当达到某种条件后,再由这个容器发送给另一端,称为延迟消息通讯(异步通信)

如下:如果我们不使用MQ的话由订单直接调用其他的方法就会有几个问题:

1.过度耦合:如果后面创建订单时,需要触发新的动作,那就得去改代码,在原有的创建订单函数末尾,再追加一行代码

2.缺少缓冲:如果创建订单时,会员系统恰好处于非常忙碌或者宕机的状态,那这时更新会员信息就会失败,我们需要一个地方,来暂时存放无法被消费的消息

解决:需要一个消息中间件,来实现解耦和缓冲的功能.

二,RabbitMQ介绍:

2.1什么是RabbitMQ?

RabbitMQ是一个功能强大的消息队列中间件,被广泛应用于分布式系统、微服务架构和异步任务处理等场景。它提供了丰富的特性和灵活的配置选项,能够满足各种不同的需求。同时也有其他的MQ,RabbitMQ只是消息队列的一种。

2.2RabbitMQ组成?
  1. 消息队列:消息队列是一种在应用程序之间进行异步通信的方式。发送方将消息发送到队列,接收方从队列中接收消息并进行处理。这种方式能够解耦发送方和接收方,提高系统的可靠性和可扩展性。

  2. AMQP协议:RabbitMQ使用AMQP(Advanced Message Queuing Protocol)作为消息传递的协议。AMQP是一个标准化的消息传递协议,支持多种编程语言和操作系统。

  3. 生产者和消费者:RabbitMQ中的消息发送方称为生产者,消息接收方称为消费者。生产者将消息发送到队列中,而消费者则从队列中接收并处理消息。

  4. 队列:队列是RabbitMQ中存储消息的地方。消息会被顺序写入队列,并按照先进先出的原则进行处理。

  5. 交换机:交换机是RabbitMQ中消息的路由器,它决定了消息应该发送到哪个队列。根据不同的路由策略,交换机可以将消息发送到一个或多个队列。

  6. 绑定:绑定是将交换机和队列关联起来的过程。绑定可以指定特定的路由规则,从而让交换机将消息发送到指定的队列。

  7. 路由策略:RabbitMQ支持多种路由策略,包括直接路由、主题路由和扇形路由等。不同的路由策略适用于不同的场景,可以实现灵活的消息路由。

  8. 可靠性:RabbitMQ提供了多种机制来确保消息的可靠传递,包括持久化、确认机制和发布者确认等。这些机制可以防止消息丢失或重复消费。

2.3RabbitMQ工作原理

RabbitMQ的工作原理主要基于生产者-消费者模型和消息队列。以下是其基本的工作流程:

生产者:生产者是创建消息的应用程序。它创建消息并发送到RabbitMQ。

队列:队列是RabbitMQ的内部结构,用于存储消息。多个生产者可以发送消息到一个队列,多个消费者可以从一个队列中获取消息。

交换器:生产者发送消息到交换器(Exchange),然后交换器根据一定的规则(路由键)将消息路由到一个或多个队列。RabbitMQ提供了几种类型的交换器,如直接交换器、主题交换器、头交换器和扇出交换器。

消费者:消费者是接收消息的应用程序。消费者连接到RabbitMQ并订阅一个队列,当新的消息到达队列时,RabbitMQ会将消息推送给消费者,或者消费者可以主动从队列中拉取消息。

消息确认:当消费者处理完一个消息后,它需要向RabbitMQ发送一个确认,告诉RabbitMQ这个消息已经被处理,可以从队列中删除。如果消费者处理消息时发生错误,它可以发送一个拒绝,告诉RabbitMQ这个消息没有被正确处理。

持久化:为了防止消息丢失,RabbitMQ提供了消息持久化的功能。生产者在发送消息时可以设置消息为持久化,RabbitMQ会将这些消息存储到磁盘,即使RabbitMQ服务器重启,这些消息也不会丢失。

通过这种方式,RabbitMQ可以在分布式系统中实现消息的可靠传递。

RabbitMQ是一个实现了AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,用Erlang语言.

Server(Broker):接收客户端连接,实现AMQP协议的消息队列和路由功能的进程.

Virtual Host:虚拟主机的概念,类似权限控制组,一个Virtual Host里可以有多个Exchange和Queue.

Exchange:交换机,接收生产者发送的消息,并根据Routing Key将消息路由到服务器中的队列Queue.

ExchangeType:交换机类型决定了路由消息行为,

RabbitMQ中有三种类型Exchange,分别是fanout、direct、topic.

Message Queue:消息队列,用于存储还未被消费者消费的消息. Message:由Header和body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、优先级是多少、由哪个Message Queue接收等.body是真正需要发送的数据内 容.

BindingKey:绑定关键字,将一个特定的Exchange和一个特定的Queue绑定起来.

2.4RabbitMQ在企业项目中使用场景:

有一个商城项目,可以使用RabbitMQ来实现以下场景:

  1. 异步订单处理:当用户下单后,可以将订单信息封装成消息发送到订单队列中。然后由消费者异步地进行订单处理,例如库存扣减、物流跟踪等。这样可以提高系统的响应速度和可靠性。

  2. 库存同步:在商城项目中,库存是一个重要的资源。可以使用RabbitMQ来实现库存同步,例如将库存变更的消息发送到库存队列中,然后由消费者将库存信息同步到数据库中。

  3. 商品推荐:在商城项目中,推荐系统是一个重要的组件。可以使用RabbitMQ来实现商品推荐的场景,例如将用户浏览历史封装成消息发送到推荐队列中,然后由推荐引擎进行商品推荐。

  4. 优惠券发放:在商城项目中,优惠券是一种常见的促销方式。可以使用RabbitMQ来实现优惠券的发放,例如将优惠券信息封装成消息发送到优惠券队列中,然后由消费者将优惠券发放给符合条件的用户。

  5. 日志收集:商城项目通常需要进行大量的日志记录和统计。可以使用RabbitMQ来实现日志收集,例如将日志信息封装成消息发送到日志队列中,然后由消费者对日志进行分类、统计和分析。

2.5Docker安装部署RabbitMQ

下载镜像:

复制代码
docker pull rabbitmq:management
复制代码
docker run -d \ --name my-rabbitmq \

-p 5672:5672 -p 15672:15672 \

-v /home/rabbitmq:/var/lib/rabbitmq \ --hostname my-rabbitmq-host \

-e RABBITMQ_DEFAULT_VHOST=my_vhost \

-e RABBITMQ_DEFAULT_USER=admin \

-e RABBITMQ_DEFAULT_PASS=admin \

--restart=always \ rabbitmq:management

--hostname:主机名(RabbitMQ的一个重要注意事项是它根据所谓的 "节点名称" 存储数据,默认为主机名)

-p:这里有两个端口

-e:指定环境变量: RABBITMQ_DEFAULT_VHOST:默认虚拟机名 RABBITMQ_DEFAULT_USER:默认的用户名

RABBITMQ_DEFAULT_PASS:默认用户名的密码

执行流程:用于在Docker中运行RabbitMQ的命令。它会创建一个名为"my-rabbitmq"的容器,并映射5672和15672端口到主机上,分别用于AMQP和管理界面访问。容器的数据存储在主机的"/home/rabbitmq"目录下,RabbitMQ的默认虚拟主机为"my_vhost",默认用户名和密码为"admin"。容器会在Docker启动时自动重启。

查看my-rabbitmq是否在运行:

docker logs my-rabbitmq

2.6创建springboot项目嵌套RabbitMQ

创建两级父子项目,父项目为maven项目mq1,子项目为springboot项目有两个provider,consumer

修改application的配置

consumer.application

复制代码
server:
    port: 9999
spring:
    application:
        name: xx
    rabbitmq:
        host: 192.168.124.131
        username: springboot
        password: 123456
        port: 5672
        virtual-host: my_vhost

provider.application

复制代码
server:
    port: 8888
spring:
    application:
        name: xx
    rabbitmq:
        host: 192.168.124.131
        username: springboot
        password: 123456
        port: 5672
        virtual-host: my_vhost

这是一个创建MQ的方法

复制代码
@Configuration
@SuppressWarnings("all")
public class RabbitConfig {
@Bean
public Queue firstQueue() {
return new Queue("firstQueue");
}
}
复制代码
Queue("firstQueue");是内置方法

firstQueue是消息队列的名字。

导入指定的包:

AmqpTemplate pom文件中引入了

复制代码
    @Autowired
    private AmqpTemplate rabbitTemplate;
    @RequestMapping("/sender")
    @ResponseBody
    public String sendFirst() {
        rabbitTemplate.convertAndSend("firstQueue", "Hello World");
        return "zhu";
    }
传递字符串类型

访问:localhost:8888/sender

报错:Connection refused: connect

解决添加连接的账号密码:

检查:

继续访问:localhost:8888/sender

成功:

构建消费者 Consumer

传递实体类型

使用了@Autowired注解来自动注入AmqpTemplate和ObjectMapper对象。AmqpTemplate是Spring提供的一个操作RabbitMQ的工具,可以用来发送和接收消息。ObjectMapper是Jackson库提供的一个工具,可以用来将对象转换为JSON字符串,或者将JSON字符串转换为对象。

sender02方法创建了一个User对象,然后使用ObjectMapper将这个对象转换为JSON字符串,然后发送这个JSON字符串到名为secondQueue的队列中。消费者会接收指定的队列消息使用了log.warn来打印接收到的消息从而消费。

复制代码
    @RequestMapping("/sender2")
    @ResponseBody
    public String sender2() {
        com.example.provide.User user = new com.example.provide.User("1", "1");
        rabbitTemplate.convertAndSend("secondQueue", user);
        return "zhu2";
    }
复制代码
package com.example.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@SuppressWarnings("all")
@Component
@Slf4j
@RabbitListener(queues = "firstQueue")
public class SecondReceiver {


    @RabbitHandler
    public void send(User user) {
        log.warn("接收到:" + user);
        }
    }

这里显示不能够这样传递:

原因是

SimpleMessageConverter 这个类时,接收到了不支持的消息类型。SimpleMessageConverter 只支持 String、byte[] 和 Serializable 类型的消息内容。

根据异常信息,你传递给它的消息内容是 com.example.provide.User 类型,因此引发了这个异常。你需要将消息内容转换为 SimpleMessageConverter 支持的类型。

生产者:

复制代码
    @RequestMapping("/sender2")
    @ResponseBody
    public String sender2() throws JsonProcessingException {
        User user = new User("1", "1");
        // 序列化对象转换为JSON字符串
        String json = objectMapper.writeValueAsString(user);
        rabbitTemplate.convertAndSend("secondQueue", json);
        return "zhu2";
    }

实体:注意实现Serializable

复制代码
package com.example.provide;


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@SuppressWarnings("all")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String username;
private String userpwd;
}

访问响应:

复制代码
    @RequestMapping("/sender2")
    @ResponseBody
    public String sender2() throws JsonProcessingException {
        User user = new User("1", "1");
        // 序列化对象转换为JSON字符串
        String json = objectMapper.writeValueAsString(user);
        rabbitTemplate.convertAndSend("secondQueue", json);
        return "zhu2";
    }

消费者:

复制代码
@Component
@Slf4j
@RabbitListener(queues = "secondQueue")
public class SecondReceiver {
    @Autowired
    private ObjectMapper objectMapper;

    @RabbitHandler
    public void send(String json) throws JsonProcessingException {
        User user = objectMapper.readValue(json, User.class);
        // 处理user对象
        log.warn("接收到:" + user.toString());
    }

实体:注意实现Serializable

复制代码
package com.example.consumer;


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;

@SuppressWarnings("all")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String username;
private String userpwd;
}
复制代码
@Component
@Slf4j
@RabbitListener(queues = "secondQueue")
public class SecondReceiver {
    @Autowired
    private ObjectMapper objectMapper;

    @RabbitHandler
    public void send(String json) throws JsonProcessingException {
        User user = objectMapper.readValue(json, User.class);
        // 处理user对象
        log.warn("接收到:" + user.toString());
    }
访问测试:

总结:

为什么使用消息队列?

答:1.业务解耦,2实现异步,3.流量削峰填谷(时间换空间)

消息队列:同步与异步差异

同步:

优点:时效性强,立即得到结果

缺点:1.耦合度高(加业务导致改代码困难)

、 2.性能:每次执行调用需要等待上一个进程走完之后才进行

3.cpu资源浪费,等待需要执行后再执行

4.练级失败,一个服务或者进程甭溃,会导致集体阵亡

异步:

优点:1.降低耦合度,2.cpu资源运用合理,3.流量削峰填谷(时间换空间)

缺点:效率没有同步高

认真写博客的人,见一个少一个🤩🤩🤩🤩🤩🤩🤩🤩🤩

👍 点赞支持,⭐️ 收藏学习,❤️ 关注不迷路~

💬 如有错漏请不吝指正~

平顶山大师-CSDN博客

https://blog.csdn.net/m0_73647713?spm=1011.2266.3001.5343

相关推荐
初次攀爬者11 小时前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者2 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧4 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖4 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农4 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者4 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端
业精于勤_荒于稀4 天前
物流订单系统99.99%可用性全链路容灾体系落地操作手册
分布式
Ronin3054 天前
信道管理模块和异步线程模块
开发语言·c++·rabbitmq·异步线程·信道管理
Asher05094 天前
Hadoop核心技术与实战指南
大数据·hadoop·分布式
凉凉的知识库4 天前
Go中的零值与空值,你搞懂了么?
分布式·面试·go