一 简介
二 优缺点
三 安装
- 下载erlang并安装(最好从官网下最新版,不然rabbitmq会提示不支持)
- 添加ERLANG_HOME的环境变量,其值指向erlang的安装目录,同时将%ERLANG_HOME%\bin加入到Path中,最后打开命令行,输入erl,如果出现erlang的版本信息就表示erlang语言环境安装成功;
- 下载RabbitMQ 并安装
- 安装RabbitMQ-Plugins(管理界面):cd进入rabbitmq的sbin目录,输入:rabbitmq-plugins enable rabbitmq_management命令;
- 插件安装完,浏览器输入http://localhost:15672,登录界面输入用户名:guest,密码:guest登录管理界面。
四 架构说明
- 消息发送过程
- producer 发送消息过程:
- 1.1 创建connection;建立网络连接;一个用户对应一个vhost,也就是一个用户空间,各个空间资源是互相隔离的。用户创建可在管理界面admin创建。
- 1.2 创建channel;类似session。一个connection可以创建多个channel;一个channel存活期间,会对应多个exchange,多个queue;
- 1.3 通过channel声明queue。这样通过channel发送的消息才有可能会发送到这些queue中,一个channel可以声明多个queue,在声明时可以参数配置此queue是否持久化。可能发送到这些queue,而不是一定会发送到,只是一个queue的范围;
- 1.4 在消息发送之前,需要根据下项目的需要,在rabitMQ的管理界面创建多个exchange(direct类型/fanout类型/topic类型),以及针对每个exchange设定它的routingKey,以及把exchange和queue通过routingKey绑定到对应的queue上。
- fanout类型:不匹配,直接把消息投递到所有与它关联的queue;
- direct类型:完全匹配routingKey;系统默认的exchange就是direct类型,并且系统默认的exchange对应的queue都有个routingKey,也就是queuename。
- topic类型:模糊匹配,和#对routekey匹配(routingkey多个单词用.隔开)。Routing Key为一个句点号“.”分隔的字符串(我们将被句点号". "分隔开的每一段独立的字符串称为一个单词如"stock.usd.nyse"、"nyse.vmw"、"quick.orange.rabbit"。Binding Key与Routing Key一样也是句点号“. ”分隔的字符串。
Binding Key中可以存在两种特殊字符""与"#",用于做模糊匹配,其中"*"用于匹配一个单词,"#"用于匹配多个单词(可以是零个)。
https://dbaplus.cn/news-141-1464-1.html
- 1.5 消息的发送是通过channel,发送到exchange,然后exchange通过类型匹配和routeingKey把消息路由到对应的queue上,如果该消息匹配多个queue,就都会发送,如果一个queue有多个匹配,只会发送一次到这个queue。
五 代码范例
package com.qhs.mq.rabbitmq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class RabbitMsgProducer {
public static void main(String[] args) {
testProduce();
}
private static void testProduce(){
ConnectionFactory factory = null;
Connection connection = null;
Channel channel = null;
factory = new ConnectionFactory();
factory.setUsername("guest");
factory.setPassword("guest");
factory.setHost("localhost");
try {
connection = factory.newConnection();
channel = connection.createChannel();
channel.queueDeclare("qhs-queue1", false, false, false, null);
channel.queueDeclare("qhs-queue2", false, false, false, null);
channel.queueDeclare("qhs-queue3", true, false, false, null);
channel.queueDeclare("qhs-queue4", true, false, false, null);
String message = "hello world .....";
channel.basicPublish("", "qhs-queue1", null, message.getBytes("UTF-8"));
channel.basicPublish("", "qhs-queue2", null, message.getBytes("UTF-8"));
channel.basicPublish("", "qhs-queue3", null, message.getBytes("UTF-8"));
channel.basicPublish("dire1", "qhs-queue4", null, message.getBytes("UTF-8"));
System.out.println("发送 message[" + message + "] success!");
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
try {
// 关闭资源
channel.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
集群部署

- RabbitMQ节点不完全拷贝特性
abbitMQ的集群是由多个节点组成的,但不是每个节点都有所有队列的完全拷贝。其他非所有者节点只知道队列的元数据,和指向该队列节点的指针。- 集群节点类型
节点的存储类型分为两种:
- 磁盘节点
- 内存节点
磁盘节点就是配置信息和元信息存储在磁盘上,内次节点把这些信息存储在内存中,当然内次节点的性能是大大超越磁盘节点的。
单节点系统必须是磁盘节点,否则每次你重启RabbitMQ之后所有的系统配置信息都会丢失。
RabbitMQ要求集群中至少有一个磁盘节点,当节点加入和离开集群时,必须通知磁盘节点。
- 如果唯一磁盘的磁盘节点崩溃,集群是可以保持运行的,但你不能更改任何(配置)东西。
- 解决方案:在集群中设置两个磁盘节点,只要一个可以,你就能正常操作。对于队列,可以通过配置镜像队列的方式,这样一个队列就在其他节点有了一个复制的备份队列。当原来节点挂了,就会选举从队列所在节点为可用队列。
镜像集群
当集群配置为镜像集群策略时,镜像队列允许内建双活冗余选项,与普通队列不同,镜像节点在集群中的其他节点拥有从队列拷贝,一旦主节点不可用,最老的从队列将被选举为新的主队列。等于镜像集群中所有节点都有一个完整的备份。
缺点就是单节点的数据压力增大。
镜像队列的工作原理:在某种程度上你可以将镜像队列视为,拥有一个隐藏的fanout交换器,它指示者信道将消息分发到从队列上。
集群重启顺序
集群重启的顺序是固定的,并且是相反的。如下所述:
- 启动顺序:磁盘节点 => 内存节点
- 关闭顺序:内存节点 => 磁盘节点
最后关闭必须是磁盘节点,不然可能回造成集群启动失败、数据丢失等异常情况。
网友评论