RabbitMQ ( 一 ):安装RabbitMQ、了解RabbitMQ相关名词 以及 4种Exchange交换器

一、MQ 的相关概念

1.1、 什么是MQ

MQ(Message Queue)是一种消息代理(接收和转发消息),本质是个队列,遵循 FIFO 先进先出原则,只不过队列中存放的内容是 Message 而已。


1.2、MQ的作用
1.2.1、异步处理

cd

应用场景:用户注册。

  • 同步调用:用户注册成功后,将用户注册信息写入数据库( 耗时50ms ),然后调用发邮件方法给用户发一封邮件( 耗时50ms ),接着再给用户发一条短信( 耗时50ms )。所以在150ms后响应用户,注册成功了。

  • 多线程处理:用户注册成功后,先将用户注册信息写入数据库( 耗时50ms ),然后通过多线程并发执行发邮件和发短信操作( 耗时50ms )。所以在100ms后响应用户,注册成功了。

  • 消息队列异步处理:用户注册成功后,先将用户注册信息写入数据库( 耗时50ms ),然后将注册成功的信息写入消息队列中( 这个过程耗时很短 ),写入消息队列之后就可以立马响应用户,注册成功了。而发邮件和发短信操作,可以通过异步读取的方式从消息队列中取出注册成功的信息,给用户发邮件和发短信。(因为用户只需要知道注册成功了就行,并不需要很快就受到邮件和短信)。


1.2.2、应用解耦

解析:使用消息队列来作为两个系统的通讯媒介进行数据传递,使得两个系统不再相互依赖,解耦两个应用。

cd

  • 将订单系统 和 库存系统都单独抽取出来 ( 可以通过微服务的方式来抽取一个服务 ),订单系统将下单信息写入消息队列,库存系统通过订阅消息队列获取订单信息,进行库存计算相关操作。

1.2.3、流量削峰

cd

应用场景:1000万用户秒杀1万件商品

  • 如果1000万用户发送请求,每个请求都要去判断库存,这样不仅麻烦,而且可能会卡死。

  • 用户的秒杀请求直接进入队列,对消息队列设置定长,只能存储一万个数据( message )。先到先进队,队列满了之后,后面999万个用户的请求进不了队列,请求被抛弃,响应秒杀失败。


二、安装RabbitMQ

2.1、安装RabbitMQ

docker拉取rabbitmq镜像,拉取带management标签的镜像,带management标签的rabbitmq是带web管理界面的,方便我们操作。

docker pull rabbitmq:3.9-management

可以使用docker中国官方镜像加速加速地址拉取:registry.docker-cn.com/library

例如:docker pull registry.docker-cn.com/library/rabbitmq:3.9-management


如果使用镜像加速地址后,报:Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)错误
则vi /etc/resolv.conf编辑文件
添加下面两行
nameserver 8.8.8.8
nameserver 8.8.4.4
重启

2.2、运行RabbitMQ
docker run -d -p 5672:5672 -p 15672:15672 --name cd-rabbitmq b47e1fb19937

run 运行
-d 在后台运行
-p 端口映射(将服务器的端口映射到docker中,否则外面只能访问到centos,而访问不到docker
带management管理界面的rabbitmq有两个端口,一个是客户端与rabbitmq通信的端口5672,一个是管理界面访问web页面的端口15672
--name 给运行的容器起个名字
b47e1fb19937 要启动镜像的id


虚拟机关闭后,RabbitMQ容器也会关闭,(使用docker ps查看不到了,但可以用docker ps -a可以看到关闭了的容器)
使用docker start 容器ID 或 docker start 容器名 来重新启动已经关闭的容器

2.3、使用 youip:15672 访问 RabbitMQ 的web页面

cd


三、RabbitMQ相关名词解释

cd


3.1、Message

消息,由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括router-key ( 路由键 )、priority ( 相对其它消息的优先级 )、delivery-mode ( 指出该消息可能需要持久化存储)等。

3.2、Publisher

消息的生产者,可以理解为一个向客户端发布消息的客户端程序。

3.3、Exchange

交换器,用来接收生产者的发送的消息,并将这些消息路由给服务器中的队列。

Exchange有4种类型,direct ( 默认 ),fanout、topic 和 headers,不同类型的的Exchange转发消息的策略有所区别。

3.4、Queue

消息队列,用来保存消息知道发送给消费者。它是消息的容器,也是消息的终点。一个消息可以投入一个或多个消息队列。消息一直在队列里,等待消费者连接到这个队列将其取走。

3.5、Binding

绑定,用于消息队列和交换器指尖的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个绑定构成的路由表。

3.6、Connection

网络连接,比如一个tcp连接

3.7、Channel

信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的tcp连接内的虚拟连接,AMQP命令都是通过信道发出去的,不管是发布消息,订阅队列还是接受消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁tcp都是非常昂贵的开销,所以引入了信道的概念,一服用一条tcp连接。

3.8、Consumer

消息的消费者,表示一个从消息队列中取得消息的客户端程序。

3.9、Virtual Host

虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP开年的基础,必须在连接时指定,RabbitMQ默认的vhost是/。

3.10、Broker

表示消息队列服务器实体。


四、RabbitMQ提供的消息模型

4.1、direct exchange

直连交换器 (默认),根据router key路由键完全匹配进行路由消息队列。


4.2、fanout exchange

主题交换器,模糊匹配

  • #号匹配一个或多个单词,*号匹配一个单词,用 . 隔开的为一个单词
  • beijing.# == beijing.queue.abc,beijing.queue.abc.xyz
  • beijing.* == beijing.abc,beijing.xyz,beijing.haha

4.3、topic exchange

扇形交换器,不处理router key路由键 ( 不匹配路由键 ),将消息投递到所有绑定的队列。


4.4、headers exchange

报头交换器,基于消息体中的headers属性内容进行匹配。


五、SpringBoot整合RabbitMQ

cd


5.1、SpringBoot自动配置
  • RabbitAutoConfiguration

  • spring-boot-starter-amqp提供了对amqp的支持

  • 需要ConnectionFactory的实现来连接消息代理

  • 提供RabbitTemplate来发送消息

  • @EnableRabbit开启支持

  • @RabbitListenner(AMQP)注解在方法上监听消息代理发送的消息


5.2、RabbitMQ中Exchange对象的一些基本属性
  • Name:交换器名称
  • Type:交换器类型 ( direct、topic、fanout、headers )
  • Durability:是否需要持久化,true表示需要持久化 ( 持久化到硬盘,可以防止RabbitMQ宕机造成消息丢失 )
  • Auto Delete:当最后一个绑定到Exchange交换器上的queue队列被删除后,是否自动删除改Exchange交换器,true表示自动删除
  • Internal:当前Exchange是否用于RabbitMQ内部使用,默认为false。
  • Arguments:扩展参数

5.3、Direct 单播模式测试

1)application.properties

#[ RabbitMQ配置 ]
#安装了rabbitmq的服务器IP
spring.rabbitmq.host=192.168.184.129
#rabbitmq服务器端口( 默认为5672 )
spring.rabbitmq.port=5672
#用户名( 默认用户名为guest )
spring.rabbitmq.username=guest
#用户密码( 默认密码为guest )
spring.rabbitmq.password=guest
#vhost虚拟主机地址( 默认为/ )
spring.rabbitmq.virtual-host=/

2)通过实体类封装消息

import lombok.*;

@Setter //setter方法
@Getter //getter方法
@ToString //toString方法
@AllArgsConstructor //全参构造
@NoArgsConstructor //无参构造
public class User {
    private Integer userId;
    private String username;
    private String password;
}

3)使用 Direct 交换器,必须指定具体的 router key 路由键,不能使用模糊匹配

@SpringBootTest
public class RabbitMQTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送消息后,Queue消息队列中相应的会增加一条消息
     */
    @Test
    public void sendMsg(){
        //对象被通过java默认序列化后发送出去
        rabbitTemplate.convertAndSend("exchange.direct", "atguigu.new", new User(1001, "张三", "123456"));
    }

    /**
     * 接收消息后,Queue消息队列中相应的会减少一条消息
     */
    @Test
    public void receiveMsg(){
        //将接收到的数据反序列化
        Object o = rabbitTemplate.receiveAndConvert("atguigu.new");
        System.out.println(o);
    }

}

4)由于RabbitMQ默认使用java默认的序列化工具进行序列化 (序列化成字节码格式),不方便查看。所以可以通过配置类配置成以json格式进行发送/接收,而不是使用jdk默认的序列化格式

@Configuration
public class RabbitMQConfig {

    /**
     * 配置RabbitMQ的消息以json格式进行发送/接收,而不是使用jdk默认的序列化格式
     * @return
     */
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

}

cd


cd


5.4、Fanout 广播模式测试

1)Fanout模式不用设置路由键 ( 不匹配路由键 ),它会将消息投递到所有绑定的队列。

@SpringBootTest
public class RabbitMQTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送消息后,所有Queue消息队列中相应的会增加一条消息
     */
    @Test
    public void sendMsg(){
        rabbitTemplate.convertAndSend("exchange.fanout", "", new User(1001, "张三", "123456"));
    }

}

2)fanout交换器绑定的所有队列都增加了一条消息

cd


5.5、@EnableRabbit + @RabbitListener:监听消息队列内容

1)在启动类中添加@EnableRabbit注解 ( 用来开启基于注解的RabbitMQ模式 )

/**
 * 自动配置:
 *     1、RabbitAutoConfiguration
 *     2、自动配置了连接工厂ConnectionFactory
 *     3、RabbitProperties封装了RabbitMQ的配置
 *     4、RabbitTemplate:给RabbitMQ发送和接收消息
 *     5、AmqpAdmin:RabbitMQ系统管理功能组件, 比如用代码创建交换器、创建队列、创建路由键,都是通过AmqpAdmin来完成
 *     6、@EnableRabbit + @RabbitListener:监听消息队列内容
 */

@EnableRabbit
@SpringBootApplication
public class SpringbootRabbitmqApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootRabbitmqApplication.class, args);
        System.out.println("项目启动成功!");
    }

}

2)使用@RabbitListener注解监听消息队列的消息 ( 只要消息队列中有消息,就能自动接收,直到队列中没有为止 )

@Service
public class UserService {

    @RabbitListener(queues = {"atguigu"})
    public void receive01(User user){
        System.out.println("atguigu队列中的消息:" + user);
    }

    @RabbitListener(queues = {"atguigu.new"})
    public void receive02(Message msg){
        System.out.println("atguigu.new队列中消息的->消息头:" + msg.getHeaders());
        System.out.println("atguigu.new队列中消息的->消息体:" + msg.getPayload());
    }

    @RabbitListener(queues = {"atguigu.emps"})
    public void receive03(User user){
        System.out.println("atguigu.emps队列中的消息:" + user);
    }

}

5.6、RabbitMQ系统管理功能组件:AmqpAdmin

1)使用RabbitMQ系统管理功能组件:AmqpAdmin来创建交换器、队列、绑定规则

@SpringBootTest
public class RabbitMQTest {

    @Autowired
    AmqpAdmin amqpAdmin;

    /**
     * 使用AmqpAdmin系统管理组件创建exchange交换器
     */
    @Test
    public void createExchange(){
        /**
         * 1.交换器名称
         * 2.是否持久化
         * 3.当最后一个绑定在Exchange交换器上的queue队列被删除后,是否自动删除改Exchange交换器
         */
        amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange", true, false));
    }

    
    /**
     * 使用AmqpAdmin系统管理组件创建queue队列
     */
    @Test
    public void createQueue(){
        /**
         * 1.队列名称
         * 2.是否持久化
         */
        amqpAdmin.declareQueue(new Queue("amqpadmin.queue", true));
    }
    

    /**
     * 使用AmqpAdmin系统管理组件创建Binding绑定规则
     */
    @Test
    public void createBinding(){
        /**
         * 1.绑定的目的地( 可以使Queue 或 Exchange的名称 )
         * 2.绑定的目的地的类型( 可以使Queue 或 Exchange )
         * 3.交换机名称
         * 4.路由键
         * 5.参数信息(Map类型)
         */
        amqpAdmin.declareBinding(new Binding("amqpadmin.queue",
                Binding.DestinationType.QUEUE, "amqpadmin.exchange",
                "amqp.news", null));
    }

    

    /**
     * 使用AmqpAdmin系统管理组件删除Exchange交换器
     */
    @Test
    public void deleteExchange(){
        amqpAdmin.deleteExchange("amqpadmin.queue");
    }

    
    /**
     * 使用AmqpAdmin系统管理组件删除Queue队列
     */
    @Test
    public void deleteQueue(){
        amqpAdmin.deleteQueue("amqpadmin.exchange");
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

家师曹先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值