RabbitMQ

RabbitMQ

一、RabbitMQ介绍

1.1.什么是mq

消息队列(Message Queue,简称MQ):是在消息的传输过程中保存消息的容器。用于分布式系统之间进行通信。

在这里插入图片描述

1.2.什么AMQP协议?

AMQP,即 Advanced Message Queuing Protocol(高级消息队列协议)
规定的接口:
connection:连接rabbitmq的通道
channel:轻量级的connection
exchange:只负责分发消息
queue:存储消息的容器

1.3.什么是RabbitMQ?

AMQP,即 Advanced Message Queuing Protocol(高级消息队列协议),是一个网络协议,是应用层协议的一个开放标准,为面向消息、erlang语言编写的实现AMQP协议的消息中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。2006年,AMQP规范发布。类比HTTP。

1.4.为什么要使用RabbitMQ ?

1.4.1.解耦

传统模式:系统间耦合性太强,如图所示,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!

在这里插入图片描述

中间件模式:将消息写入消息队列,需要消息的系统自己从消息队列中订阅。例:a服务本来只调用b、c服务,若添加d服务时无需修改a服务的代码

在这里插入图片描述

1.4.2.异步

传统模式: 一些非必要的业务逻辑以同步的方式运行,太耗费时间

在这里插入图片描述

中间件模式: 将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度。例:a服务把消息发送到mq,b、c服务接收消息以异步的方式运行

在这里插入图片描述

1.4.3.削峰

传统模式:并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常

在这里插入图片描述

中间件模式: 系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息

在这里插入图片描述

二、RabbitMQ安装

2.1.下载

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

请添加图片描述

2.2.安装erlang语言环境

上传安装包

在这里插入图片描述

注:我是上传到 /usr/upload

依次执行命令:

cd /usr/upload
rpm -ivh esl-erlang-17.3-1.x86_64.rpm --force --nodeps
rpm -ivh esl-erlang_17.3-1~centos~6_amd64.rpm --force --nodeps
rpm -ivh esl-erlang-compat-R14B-1.el6.noarch.rpm --force --nodeps

2.3.安装RabbitMQ

上传安装包

在这里插入图片描述

按rabbitmq

rpm -ivh rabbitmq-server-3.4.1-1.noarch.rpm

在这里插入图片描述

2.4.启动、停止

service rabbitmq-server start

service rabbitmq-server stop

service rabbitmq-server restart

service rabbitmq-server status

2.5.设置开机启动

chkconfig rabbitmq-server on

2.6.防火墙开放15672端口

/sbin/iptables -I INPUT -p tcp --dport 15672 -j ACCEPT

/etc/rc.d/init.d/iptables save

2.7.开启web界面管理工具

rabbitmq-plugins enable rabbitmq_management

service rabbitmq-server restart

在这里插入图片描述

2.8.创建账户

这里我们以创建个admin帐号,密码1111为例,创建一个账号并支持远程ip访问。

1.创建账号

rabbitmqctl  add_user admin 1111

2.设置用户角色

rabbitmqctl  set_user_tags admin  administrator

3.设置用户权限

rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"

4.设置完成后可以查看当前用户和角色(需要开启服务)

rabbitmqctl list_users

在这里插入图片描述

账号guest具有所有的操作权限,并且又是默认账号,出于安全因素的考虑,guest用户只能通过localhost登陆

5.测试

​ 浏览器输入:serverip:15672。其中serverip是RabbitMQ-Server所在主机的ip,15672是RabbitMQ-Server的端口号

在这里插入图片描述

2.9.管理界面

在这里插入图片描述

connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况

channels:通道,建立连接后,会形成通道,消息的投递获取依赖通道。

Exchanges:交换机,用来实现消息的路由

Queues:队列,即消息队列,消息存放在队列中,等待消费,消费后被移除队列。

端口:

5672: rabbitMq的编程语言客户端连接端口

15672:rabbitMq管理界面端口

25672:rabbitMq集群的端口

2.10.添加用户

如果不使用guest,我们也可以自己创建一个用户:

在这里插入图片描述

1、 超级管理员(administrator)

可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。

2、 监控者(monitoring)

可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)

3、 策略制定者(policymaker)

可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。

4、 普通管理者(management)

仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。

5、 其他

无法登陆管理控制台,通常就是普通的生产者和消费者。

2.11.创建Virtual Hosts

虚拟主机:类似于mysql中的database。他们都是以“/”开头

在这里插入图片描述

2.12.设置权限

1、点击用户名

在这里插入图片描述

2、设置权限

在这里插入图片描述

3、查看效果

在这里插入图片描述

三、创建RabbitMQ工程

3.1.创建工程

在这里插入图片描述

3.2.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>
    <groupId>com.bjpowernode</groupId>
    <artifactId>springboot_rabbitmq</artifactId>
    <version>1.0-SNAPSHOT</version>

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

</project>

3.3.util

抽取一个建立RabbitMQ连接的工具类,方便其他程序获取连接:

package com.bjpowernode.util;

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

public class ConnectionUtil {
    /**
     * 建立与RabbitMQ的连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception {
        //定义连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置服务地址
        factory.setHost("192.168.233.132");
        //端口
        factory.setPort(5672);
        //设置账号信息,用户名、密码、vhost
        factory.setUsername("admin");
        factory.setPassword("1111");
        factory.setVirtualHost("/");
        // 通过工程获取连接
        Connection connection = factory.newConnection();
        return connection;
    }
}

四、五种消息模型

4.1.Simple-简单模型

RabbitMQ是一个消息代理:它接受和转发消息。 你可以把它想象成一个邮政信箱

RabbitMQ与邮局的主要区别是它不处理纸张,而是接受,存储和转发数据消息的二进制数据块。

在这里插入图片描述

P(producer/ publisher):生产者,一个发送消息的用户应用程序。

C(consumer):消费者,消费和接收有类似的意思,消费者是一个主要用来等待接收消息的用户应用程序

队列(红色区域):rabbitmq内部类似于邮箱的一个概念。虽然消息流经rabbitmq和你的应用程序,但是它们只能存储在队列中。队列只受主机的内存和磁盘限制,实质上是一个大的消息缓冲区。许多生产者可以发送消息到一个队列,许多消费者可以尝试从一个队列接收数据。

总之:

生产者将消息发送到队列,消费者从队列中获取消息,队列是存储消息的缓冲区。

 producer----->|queue|------>consumer

        手动ack:
            channel.basicConsume(, false, );//不自动ack

            try{
                //业务逻辑....
                channel.basickAak(envelope.getDeliveryTag(), false);//手动ack
            }

好处:保证消费者把消息成功消费(理论)

消息确认机制(ACK)

RabbitMQ怎么知道消息被接收了呢?

如果消费者领取消息后,还没执行操作就挂掉了呢?或者抛出了异常?消息消费失败,但是RabbitMQ无从得知,这样消息就丢失了!

因此,RabbitMQ有一个ACK机制。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:

  • 自动ACK:消息一旦被接收,消费者自动发送ACK
  • 手动ACK:消息接收后,不会发送ACK,需要手动调用

大家觉得哪种更好呢?

这需要看消息的重要性:

  • 如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
  • 如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除。如果此时消费者宕机,那么消息就丢失了。

4.2.Work-工作模型

工作队列或者竞争消费者模式

在这里插入图片描述

 producer----->|queue|------>多consumer

        能者多劳:
            channel.basicQos(1);

如何防止消息堆积?(多consumer+能者多劳)

1)采用workqueue,多个消费者监听同一队列。

2)接收到消息以后,而是通过线程池,异步消费。

4.3.Fanout-广播模型

Fanout,也称为广播。

流程图:

在这里插入图片描述

在广播模式下,消息发送流程是这样的:

  • 1) 可以有多个消费者
  • 2) 每个消费者有自己的queue(队列)
  • 3) 每个队列都要绑定到Exchange(交换机)
  • 4) 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
  • 5) 交换机把消息发送给绑定过的所有队列
  • 6) 队列的消费者都能拿到消息。实现一条消息被多个消费者消费
  • 要注意代码中:队列需要和交换机绑定
producer----->exchange------------>|多queue|------>多consumer

注意:exchange只负责分发消息,若没有queue绑定到交换器上则会把消息丢弃

4.4.Direct-定向模型

有选择性的接收消息

在订阅模式中,生产者发布消息,所有消费者都可以获取所有消息。

在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消息引导到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。

但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。

在Direct模型下,队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)

消息的发送方在向Exchange发送消息时,也必须指定消息的routing key。

在这里插入图片描述

P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。

X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列

C1:消费者,其所在队列指定了需要routing key 为 error 的消息

C2:消费者,其所在队列指定了需要routing key 为 info、error、warning 的消息

producer----->exchange-----(routingkey)------->|多queue|------>多consumer

 注意:routingkey灵活控制exchange把消息分发到哪个queue

5.5.Topic-主题模型

Topic类型的ExchangeDirect相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key` 的时候使用通配符!

Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert

通配符规则:

`#`:匹配一个或多个词

`*`:匹配不多不少恰好1个词

举例:

`audit.#`:能够匹配`audit.irs.corporate` 或者 `audit.irs`

`audit.*`:只能匹配`audit.irs`

在这里插入图片描述

                               bind
producer----->exchange-----(*.routingkey.#)------->|多queue|------>多consumer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值