RabbitMQ简介:
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
RabbitMQ与其他消息中间件相比的优势:
ActiveMQ是老牌消息中间件,支持丰富的API,但不支持高并发,适合中小型企业。
Kafka追求高吞吐量,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。但是RocketMQ的一些重要功能并没有开源,如:事务。
RabbitMQ支持高并发,支持事务,应用于对数据一致性、稳定性和可靠性要求高的场景。由于是使用Erlang语言开发,所以RabbitMQ先天契合Spring。
RabbitMQ 在Linux环境的安装
-
下载Rbbitmq及其相关安装包(官网地址:https://www.rabbitmq.com)
-
在安装rabbitmq之前,首先安装erlang和socat
rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm
rpm -ivh socat-1.7.3.2-2.el7.x86_64.rpm
- 复制配置文件
cp /usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
4.修改配置文件
vim /etc/rabbitmq/rabbitmq.config
删除下方图片选中区域前的“%%”和后面的“,”(允许使用 “guest” 远程访问)
- 启动Rabbitmq中的管理插件
rabbitmq-plugins enable rabbitmq_management
- 启动RabbitMQ的服务
systemctl start rabbitmq-server
- 查看服务状态
systemctl stop rabbitmq-server
8.访问web管理页面
以游客用户登录,账号和密码默认为guest
SpringBoot中使用RabbitMQ
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
-
添加用户并设置密码
-
配置配置文件
端口默认为5672
spring:
application:
name: springboot_rabbitmq
rabbitmq:
host: 49.235.86.16
port: 5672
username: ems
password: 123
virtual-host: /ems
- 多种Rabbitmq模型的运用
- 最简单模型的运用
生产者
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void test() {
rabbitTemplate.convertAndSend("simplest", "hello simplest model");
}
消费者
@Component
@RabbitListener(queuesToDeclare = @Queue("simplest")) // 默认持久化、非独占、不自动删除队列
public class SimplestConsumer {
@RabbitHandler
public void receive(String message) {
System.out.println("message=" + message);
}
}
- work模型的运用
生产者
@Test
public void workTest() {
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("work", "hello work model");
}
}
消费者
@Component
public class WorkConsumer {
@RabbitListener(queuesToDeclare = @Queue("work"))
public void receive1(String message) {
System.out.println("work message1=" + message);
}
@RabbitListener(queuesToDeclare = @Queue("work"))
public void receive2(String message) {
System.out.println("work message2=" + message);
}
}
- 广播(发布/订阅)模型的运用
生产者
@Test
public void FanoutTest() {
rabbitTemplate.convertAndSend("logs","","hello fanout model");
}
消费者
@Component
public class FanoutConsumer {
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
exchange = @Exchange(name = "logs", type = "fanout")))
public void receive1(String message){
System.out.println("message1 = " + message);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue, //创建临时队列
exchange = @Exchange(name="logs",type = "fanout") //绑定交换机类型
))
public void receive2(String message){
System.out.println("message2 = " + message);
}
}
- 路由模型的运用
生产者
@Test
public void RoutingTest() {
rabbitTemplate.convertAndSend("logs_direct","error","hello routing model");
}
消费者
@Component
public class RoutingConsumer {
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
exchange = @Exchange(name = "logs_direct", type = "direct"), key = {"info", "error"}))
public void reveive1(String message) {
System.out.println("message1 = " + message);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
exchange = @Exchange(name = "logs_direct", type = "direct"),
key = {"error"}))
public void reveive2(String message) {
System.out.println("message2 = " + message);
}
}
- Topics模型的运用(与路由模型相似,区别在于Topics模型的RoutingKey可以使用通配符,“*”代表一个字符,“#”代表多个字符)
生产者
@Test
public void TopicTest() {
rabbitTemplate.convertAndSend("logs_topic","user.name.value","hello topic model");
}
消费者
@Component
public class TopicConsumer {
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
exchange = @Exchange(name = "logs_topic", type = "topic"),
key = {"user.*"}))
public void reveive1(String message) {
System.out.println("message1 = " + message);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
exchange = @Exchange(name = "logs_topic", type = "topic"),
key = {"user.#"}))
public void reveive2(String message) {
System.out.println("message2 = " + message);
}
}
Rabbitmq集群
- 普通集群(副本集群)
默认情况下:RabbitMQ代理操作所需的所有数据/状态都将跨所有节点复制。这方面的一个例外是消息队列,默认情况下,消息队列位于一个节点上,尽管它们可以从所有节点看到和访问
- 克隆三台机器主机名和ip映射
node1: vim /etc/hostname 加入: mq1
node2: vim /etc/hostname 加入: mq2
node3: vim /etc/hostname 加入: mq3
vim /etc/hosts加入:
10.15.0.3 mq1
10.15.0.4 mq2
10.15.0.5 mq3
- 安装rabbitmq,并同步cookie文件,在node1上执行
scp /var/lib/rabbitmq/.erlang.cookie root@mq2:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@mq3:/var/lib/rabbitmq/
- 在node2和node3执行加入集群命令
rabbitmqctl join_cluster rabbit@mq1
- 启动集群(任意节点执行)
rabbitmqctl start_app
- 查看集群状态,任意节点执行
rabbitmqctl cluster_status
- 登录管理界面
- 镜像集群
镜像队列机制就是将队列在三个节点之间设置主从关系,消息会在三个节点之间进行自动同步,且如果其中一个节点不可用,并不会导致消息丢失或服务不可用的情况,提升MQ集群的整体高可用性。
镜像集群架构是在普通集群的基础上构建,配置集群策略
- 策略说明
rabbitmqctl set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>
-p Vhost: 可选参数,针对指定vhost下的queue进行设置
Name: policy的名称
Pattern: queue的匹配模式(正则表达式)
Definition:镜像定义,包括三个部分ha-mode, ha-params, ha-sync-mode
ha-mode:指明镜像队列的模式,有效值为 all/exactly/nodes
all:表示在集群中所有的节点上进行镜像
exactly:表示在指定个数的节点上进行镜像,节点的个数由ha-params指定
nodes:表示在指定的节点上进行镜像,节点名称通过ha-params指定
ha-params:ha-mode模式需要用到的参数
ha-sync-mode:进行队列中消息的同步方式,有效值为automatic和manual
priority:可选参数,policy的优先级
- 查看当前策略
rabbitmqctl list_policies
- 添加策略
rabbitmqctl set_policy ha-all '^hello' '{"ha-mode":"all","ha-sync-mode":"automatic"}'
- 删除策略
rabbitmqctl clear_policy ha-all