RabbitMQ基本使用

目录

一、消息队列

1、Message queue 释义

2、问题思考

3、存在问题

①、过度耦合:

②、缺少缓冲:

4、优化方案

5、案例分析

①、带来的好处

②、消息队列特点

 6、Email邮件案例:

7、AMQP

8、技术选型

 9、RabbitMQ

二、Docker安装部署RabbitMQ

1、获取镜像

2、自定义容器

3、容器启动后查看日志  

4、 进入管理后台

 三、搭建RabbitMQ项目

1、登录账号

①、 配置账号

②、授权 

 2、springboot项目搭建

3、 所需依赖

4、application.yml配置 

①、provider

②、consumer

5.生产者 Provider

①.RabbitConfig

 ②、Sender

③、测试类ProviderApplicationTests

 6、消费者 consumer

①、Receiver

7、自定义数据发送

①、生产者 provider

②、消费者 consumer


一、消息队列

1、Message queue 释义

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

2、问题思考

假设我们在淘宝下了一笔订单后 , 淘宝后台需要做这些事情:
 ①. 消息通知系统:通知商家 , 你有一笔新的订单 , 请及时发货
 ②. 推荐系统:更新用户画像 , 重新给用户推荐他可能感兴趣的商品
 ③. 会员系统:更新用户的积分和等级信息

3、存在问题

①、过度耦合:

如果后面创建订单时 , 需要触发新的动作 , 那就得去改代码 , 在原有的创建订单函数末尾 , 再一行代码

②、缺少缓冲:

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

4、优化方案

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

5、案例分析

小红希望小明多读书 , 常寻找好书给小明看 , 之前的方式是这样:小红问小明什么时候有空 , 把书给小明送去 , 并亲眼监督小明读完书才走 . 久而久之 , 两人都觉得麻烦 .
后来的方式改成了:小红对小明说「我放到书架上的书你都要看」 , 然后小红每次发现不错的书都放到书架上 , 小明则看到书架上有书就拿下来看
书架就是一个消息队列,小红是生产者,小明是消费者.

①、带来的好处

  •  小红想给小明书的时候 , 不必问小明什么时候有空 , 亲手把书交给他了 , 小红只把书放到书架上就行了 . 这样小红小明的时间都更自由 .
  • 小红相信小明的读书自觉和读书能力 , 不必亲眼观察小明的读书过程 , 小红只要做一个放书的动作 , 很节省时间 .
  • 当明天有另一个爱读书的小伙伴小强加入 , 小红仍旧只需要把书放到书架上 , 小明和小强从书架上取书即可
  • 书架上的书放在那里 , 小明阅读速度快就早点看完 , 阅读速度慢就晚点看完 , 没关系 , 比起小红把书递给小明并监督小明读完的方式 , 小明的压力会小一些 .

②、消息队列特点

  1.  解耦 : 每个成员不必受其他成员影响 , 可以更独立自主 , 只通过一个简单的容器来联系 
  2.  提速 : 小红选只要做一个放书的动作 , 为自己节省了大量时间 .
  3.  广播 : 小红只需要劳动一次 , 就可以让多个小伙伴有书可读 , 这大大地节省了她的时间 也让新的小伙伴的加入成本很低 .
  4.  错峰与流控 : 小红给书的频率不稳定 , 如果今明两天连给了五本 , 之后隔三个月才又给一本 , 那小明只要在三个月内从书架上陆续取走五本书读完就行了 , 压力就不那么大了 

 6、Email邮件案例:

有大量用户注册你的软件 , 再高并发情况下注册请求开始出现一些问题 .
例如邮件接口承受不住 , 或是分析信息时的大量计算使 cpu 满载 , 这将会出现虽然用户数据记录很快的添加到数据库中了 , 但是却卡在发邮件或分析信息时的情况 .
导致请求的响应时间大幅增长 , 甚至出现超时 , 这就有点不划算了 . 面对这种情况一般也是将这些操作放入消息队列 ( 生产者消费者模型 ), 消息队列慢慢的进行处理 , 同时可以很快的完成注册请
求 , 不会影响用户使用其他功能 .

7、AMQP

一个提供统一消息服务的应用层标准高级消息队列协议 , 是一个通用的应用层协议
消息发送与接受的双方遵守这个协议可以实现异步通讯 . 这个协议约定了消息的格式和工作方式

8、技术选型

 9、RabbitMQ

RabbitMQ 是一个实现了 AMQP(Advanced Message Queuing Protocol) 高级消息队列协议的消息队列服务 , Erlang 语言 .
  • Server(Broker):接收客户端连接,实现AMQP协议的消息队列和路由功能的进程.
  • Virtual Host:虚拟主机的概念,类似权限控制组,一个Virtual Host里可以有多个ExchangeQueue.
  • Exchange:交换机,接收生产者发送的消息,并根据Routing Key将消息路由到服务器中的队列Queue.
  • ExchangeType:交换机类型决定了路由消息行为,RabbitMQ中有三种类型Exchange,分别是fanoutdirecttopic.
  • Message Queue:消息队列,用于存储还未被消费者消费的消息.
  • Message:由Headerbody组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、优先级是多少、由哪个Message Queue接收等.body是真正需要发送的数据内.
  • BindingKey:绑定关键字,将一个特定的Exchange和一个特定的Queue绑定起来.

二、Docker安装部署RabbitMQ

1、获取镜像

注意获取镜像的时候要获取management版本的,不要获取last版本的,management版本的才带有管理界面

docker pull rabbitmq : management

  

2、自定义容器

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 的一个重要注意事项是它根据所谓的 节点名称 存储数据 , 默认为主机名 )
-e :指定环境变量 :
RABBITMQ_DEFAULT_VHOST :默认虚拟机名
RABBITMQ_DEFAULT_USER :默认的用户名
RABBITMQ_DEFAULT_PASS :默认用户名的密码

3、容器启动后查看日志  

docker logs my - rabbitmq

4、 进入管理后台

 http://ip:15672

 三、搭建RabbitMQ项目

1、登录账号

①、 配置账号

②、授权 

 2、springboot项目搭建

3、 所需依赖

< dependency >
< groupId > org . springframework . boot </ groupId >
< artifactId > spring - boot - starter - amqp </ artifactId >
</ dependency >

4、application.yml配置 

①、provider

server:
  port: 8082
spring:
    application:
      name: provider
    rabbitmq:
      host: 192.168.129.123
      password: 123456
      port: 5672
      username: ysq
      virtual-host: my_vhost

②、consumer

server:
  port: 8081
spring:
    application:
      name: consumer
    rabbitmq:
      host: 192.168.129.123
      password: 123456
      port: 5672
      username: ysq
      virtual-host: my_vhost

5.生产者 Provider

①.RabbitConfig

package com.ysq.provider;
 
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@SuppressWarnings("all")
public class RabbitConfig {
    @Bean
    public Queue firstQueue() {
        return new Queue("firstQueue");
    }
}

 ②、Sender

package com.ysq.provider;
 
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
@SuppressWarnings("all")
public class Sender {
 
    @Autowired
    private AmqpTemplate rabbitTemplate;
 
    public void sendFirst() {
        rabbitTemplate.convertAndSend("firstQueue", "Hello World");
    }
}
 

③、测试类ProviderApplicationTests

package com.ysq.provider;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ProviderApplicationTests {
    @Autowired
    private Sender sender;
    @Test
    void contextLoads() {
        sender.sendFirst();
    }
}

 此时,RabbitMQ Management 中会增加一个队列 

 6、消费者 consumer

①、Receiver

package com.ysq.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;
@Component 
@Slf4j
@RabbitListener(queues = "firstQueue") 
public class Receiver {
    @RabbitHandler
    public void process(String msg) {
        log.warn("接收到:" + msg);
    }
}

7、自定义数据发送

①、生产者 provider

(1)、User

package com.ysq.provider;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String username;
    private String userpwd;
}

(2)、Sender

package com.ysq.provider;
 
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
public class Sender {
    @Autowired
    private AmqpTemplate amqpTemplate;
 
    public void sendFirst() {
        amqpTemplate.convertAndSend("firstQueue", "Hello World");
    }
 
    public void sendFirst(User user) {
        amqpTemplate.convertAndSend("firstQueue", user);
    }
 
    public void sendFirst(String json) {
        amqpTemplate.convertAndSend("firstQueue", json);
    }
 
}

(3)、测试

package com.ysq.provider;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ProviderApplicationTests {
    @Autowired
    private Sender sender;
 
    @Test
    @SneakyThrows
    void contextLoads() {
//        sender.sendFirst();
//        sender.sendFirst(new User("aa","123"));
        User u=new User("aa","123");
        ObjectMapper objectMapper=new ObjectMapper();
        sender.sendFirst(objectMapper.writeValueAsString(u));
    }
}

②、消费者 consumer

(1)、user

package com.example.consumer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String username;
    private String userpwd;
}

(2)、Receiver

package com.ysq.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;
 
@Component
@Slf4j
@RabbitListener(queues = "firstQueue")
public class Receiver {
//    @RabbitHandler
//    public void process(String msg) {
//        log.warn("接收到:" + msg);
//    }
 
//    @RabbitHandler
//    public void process(User user) {
        log.warn("接收到:" + user);
//    }
 
@RabbitHandler
@SneakyThrows
public void process(String json) {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.readValue(json,User.class);
    log.warn("接收:" + json);
}
 
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值