MQ全称Message Queue (消息队列), 是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。
其功能主要如图
系统的耦合性越高,容错性就越低,可维护性就越低
如图,当库存系统挂掉,订单系统也会相应的失效。当要新增X系统时,又需要修改订单系统的详细代码。
使用MQ使得应用间解耦,提升容错性和可维护性
如图,当订单系统执行时,仅需发一条消息给MQ就行了,后面的就不需要管了,然后返回下蛋成功,后面的系统只需要去MQ拿订单消息去自己系统处理。提高系统的容错性。
用户点击完下单按钮后,需要等待920ms才能得到下单响应,影响用户体验。
提升用户体验和系统吞吐量( 单位时间内处理请求的数目)。
削峰
填谷
使用了MQ之后,限制消费消息的速度为1000,这样一来, 高峰期产生的数据势必会被积压在MQ中,高峰就被”削”掉了,但是因为消息积压,在高峰期过后的一段时间内,消费消息的速度还是会维持在1000,直到消费完积压的消息,这就叫做“填谷”。
系统引入的外部依赖越多,系统稳定性越差。一旦MQ宕机,就会对业务造成影响。如何保证MQ的高可用,成为该系统的一个重点。
MQ的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过MQ进行异步调用。如何保证消息没有被重复消费,怎么处理消息丢失情况?那么保证消息传递的顺序性,成了系统设计的一个重点
A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B系统、C系统处理成功,D系统处理失败。这个问题怎么处理成为难点重点。
(1) 生产者不需要从消费者处获得反馈。引入消息队列之前的直接调用,其接口的返回值应该为空。
(2) 容许短暂的不一致性。
(3) 确实是用了有效果。即解耦、提速、削峰这些方面的收益,超过加入MQ,管理MQ这些成本。
目前业界有很多的MQ产品,例如RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、 MetaMq等,也有直接使用Redis充当消息队列的案例,而这些消息队列产品,各有侧重,在实际选型时,需要结合自身需求极MQ产品特征,综合考虑。
RabbitMQ是基于AMQP(Advanced Message Queuing Protocol (高级消息队列协议)),是一个网络协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。2006年,AMQP规范发布。
Publisher 生产者,发布者。
Exchange是交换机,用于分发消息,通过Routes路由将消息分发给Queue。
Queue是存储消息的
Consumer 消费者
整体流程:
生产者发布消息到Exchange,Exchange通过不同的规则(路由)将消息发送到不同的Queue存储,然后Consumer 从Queue中监听拿走消息去消费。
2007年,Rabbit 技术公司基于AMQP标准开发的RabbitMQ 1.0发布。RabbitMQ 采用Erlang语言开发。Erlang语言由Ericson 设计,专门为开发高并发和分布式系统的一种语言,在电信领域使用广泛。
RabbitMQ提供了6种工作模式:简单模式、work queues、Publish/Subscribe 发布与订阅模式、Routing路由模式、Topics 主题模式、RPC 远程调用模式(远程调用,不太算MQ)。
在上图的模型中,有以下概念:
1.创建连接工厂
2.设置参数
3.创建连接Connection
4.创建Channel
5.创建队列
6.发送消息
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("guest");//用户名默认guest
factory.setPassword("guest");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
channel.queueDeclare("rabbit1", false, false, false, null);
//6.发送消息
//public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, AMQP.BasicProperties props, byte[] body)
//exchange: 交换机名称,简单模式下交换机会使用默认的
//routingKey: 路由名称。
//props: 配置信息。
//body: 发送消息数据。
String body = "你好";
/*注意,如果使用简单模式,交换机置为空并且routingKey和队列名相同*/
channel.basicPublish("", "rabbit1", null, body.getBytes());
//释放资源
channel.close();
connection.close();
}
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("guest");//用户名默认guest
factory.setPassword("guest");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
channel.queueDeclare("rabbit1", false, false, false, null);
/*
public String basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoACk: 是否自动确认
callback: 回调对象
*/
Consumer consumer = new DefaultConsumer(channel) {
/**
* 回调方法,当收到消息后,会自动执行该方法
* 1.consumerTag: 标识
* 2.envelope: 获取一些信息, 交换机, 路由key...
* 3.properties: 配置信息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
System.out.println("consumerTag:" + consumerTag);
System.out.println("Exchange:"+envelope.getExchange());
System.out.println("RoutingKey:"+envelope.getRoutingKey());
System.out.println("properties:" + properties);
System.out.println("body:" + new String(body));
System.out.println("==================================================================");
}
};
channel.basicConsume("rabbit1", true, consumer);
}
1.在一个队列中如果有多个消费者,那么消费者之间对于同一个消息的关系是竞争的关系。
2. Work Queues对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。例如:短信服务部署多个,只需要有一个节点成功发送即可。
同上简单模式生产者
同简单模式消费者,复制一份就行。
在订阅模型中,多了一个Exchange角色,而且过程略有变化:
package org.example;
import com.rabbitmq.client.BuiltinExchangeType;
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 Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("guest");//用户名默认guest
factory.setPassword("guest");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建交换机
//exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, Map arguments)
//exchange:交换机名称
//type:交换机类型
//DIRECT("direct"); 定向
//FANOUT("fanout"); 扇形(广播) 发送消息到每一个与之绑定队列。
//TOPIC("topic"); 通配符匹配
//HEADERS("headers");参数匹配
//durable:是否持久化。
//autoDelete:自动删除。
//internal: 内部使用,一般false。
//arguments:参数。
String exchangeName = "test_num1";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT, true, false, false, null);
//6.创建队列
String queue1Name = "test_num1_queue1";
String queue2Name = "test_num1_queue2";
channel.queueDeclare(queue1Name, true, false, false, null);
channel.queueDeclare(queue2Name, true, false, false, null);
//7.绑定队列和交换机
//queueBind(string queue, String exchange, string routingKey)
//1. queue: 队列名称
//2. exchange: 交换机名称
//3. routingKey: 路由键,绑定规则。 如果交换机的类型为fanout,routingKey设置为空
channel.queueBind(queue1Name, exchangeName, "");
channel.queueBind(queue2Name, exchangeName, "");
//8.发送消息
String body = "私聊信息";
channel.basicPublish(exchangeName, "", null, body.getBytes());
//9.释放资源
channel.close();
connection.close();
}
}
消费者1
package org.example;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MyConsumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("guest");//用户名默认guest
factory.setPassword("guest");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
String queenName1 = "test_num1_queue1";
/*
public String basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoACk: 是否自动确认
callback: 回调对象
*/
Consumer consumer = new DefaultConsumer(channel) {
/**
* 回调方法,当收到消息后,会自动执行该方法
* 1.consumerTag: 标识
* 2.envelope: 获取一些信息, 交换机, 路由key...
* 3.properties: 配置信息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
System.out.println("==================================================================");
System.out.println("consumerTag:" + consumerTag);
System.out.println("Exchange:" + envelope.getExchange());
System.out.println("RoutingKey:" + envelope.getRoutingKey());
System.out.println("properties:" + properties);
System.out.println("body:" + new String(body));
System.out.println(queenName1 + ": '执行了'");
System.out.println("==================================================================");
}
};
channel.basicConsume(queenName1, true, consumer);
}
}
消费者2
就把queenName1 改成 test_num1_queue2 就行
生产者
package org.example.routing;
import com.rabbitmq.client.BuiltinExchangeType;
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 Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("mofeng");//用户名默认guest
factory.setPassword("263327");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建交换机
//exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, Map arguments)
//exchange:交换机名称
//type:交换机类型
//DIRECT("direct"); 定向
//FANOUT("fanout"); 扇形(广播) 发送消息到每一个与之绑定队列。
//TOPIC("topic"); 通配符匹配
//HEADERS("headers");参数匹配
//durable:是否持久化。
//autoDelete:自动删除。
//internal: 内部使用,一般false。
//arguments:参数。
String exchangeName = "test_direct";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT, true, false, false, null);
//6.创建队列
String queue1Name = "test_direct_queue1";
String queue2Name = "test_direct_queue2";
channel.queueDeclare(queue1Name, true, false, false, null);
channel.queueDeclare(queue2Name, true, false, false, null);
//7.绑定队列和交换机
//queueBind(string queue, String exchange, string routingKey)
//1. queue: 队列名称
//2. exchange: 交换机名称
//3. routingKey: 路由键,绑定规则。 如果交换机的类型为fanout,routingKey设置为空
//queue1Name绑定error
channel.queueBind(queue1Name, exchangeName, "error");
//queue2Name绑定info warring error
channel.queueBind(queue2Name, exchangeName, "info");
channel.queueBind(queue2Name, exchangeName, "warring");
channel.queueBind(queue2Name, exchangeName, "error");
//8.发送消息
String body = "这是一条rabbitmq的info信息哦";
String body1 = "这是一条rabbitmq的error信息哦";
channel.basicPublish(exchangeName, "info", null, body.getBytes());//只有q2能收到消息
channel.basicPublish(exchangeName, "error", null, body1.getBytes());//q1q2能收到消息
//9.释放资源
channel.close();
connection.close();
}
}
消费者1
package org.example.routing;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MyConsumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("mofeng");//用户名默认guest
factory.setPassword("263327");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
String queenName1 = "test_direct_queue1";
/*
public String basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoACk: 是否自动确认
callback: 回调对象
*/
Consumer consumer = new DefaultConsumer(channel) {
/**
* 回调方法,当收到消息后,会自动执行该方法
* 1.consumerTag: 标识
* 2.envelope: 获取一些信息, 交换机, 路由key...
* 3.properties: 配置信息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
System.out.println("==================================================================");
// System.out.println("consumerTag:" + consumerTag);
// System.out.println("Exchange:" + envelope.getExchange());
// System.out.println("RoutingKey:" + envelope.getRoutingKey());
// System.out.println("properties:" + properties);
System.out.println(queenName1 + ": '执行了'");
System.out.println("body:" + new String(body));
System.out.println("这是 error ");
System.out.println("==================================================================");
}
};
channel.basicConsume(queenName1, true, consumer);
}
}
消费者2
package org.example.routing;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MyConsumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("xxxxxx");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("mofeng");//用户名默认guest
factory.setPassword("263327");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
String queenName2 = "test_direct_queue2";
/*
public String basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoACk: 是否自动确认
callback: 回调对象
*/
Consumer consumer = new DefaultConsumer(channel) {
/**
* 回调方法,当收到消息后,会自动执行该方法
* 1.consumerTag: 标识
* 2.envelope: 获取一些信息, 交换机, 路由key...
* 3.properties: 配置信息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
System.out.println("==================================================================");
// System.out.println("consumerTag:" + consumerTag);
// System.out.println("Exchange:" + envelope.getExchange());
// System.out.println("RoutingKey:" + envelope.getRoutingKey());
// System.out.println("properties:" + properties);
System.out.println(queenName2 + ": '执行了'");
System.out.println("body:" + new String(body));
System.out.println("这是info error warring");
System.out.println("==================================================================");
}
};
channel.basicConsume(queenName2, true, consumer);
}
}
通配符介绍
*
: 表示一个单词。
#
: 表示一个或者多个单词。
生产者
package org.example.topic;
import com.rabbitmq.client.BuiltinExchangeType;
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 Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("47.115.217.235");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("mofeng");//用户名默认guest
factory.setPassword("263327");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建交换机
//exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, Map<String, Object> arguments)
//exchange:交换机名称
//type:交换机类型
//DIRECT("direct"); 定向
//FANOUT("fanout"); 扇形(广播) 发送消息到每一个与之绑定队列。
//TOPIC("topic"); 通配符匹配
//HEADERS("headers");参数匹配
//durable:是否持久化。
//autoDelete:自动删除。
//internal: 内部使用,一般false。
//arguments:参数。
String exchangeName = "test_topic";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC, true, false, false, null);
//6.创建队列
String queue1Name = exchangeName+"_queue1";
String queue2Name = exchangeName+"_queue2";
channel.queueDeclare(queue1Name, true, false, false, null);
channel.queueDeclare(queue2Name, true, false, false, null);
//7.绑定队列和交换机
//queueBind(string queue, String exchange, string routingKey)
//1. queue: 队列名称
//2. exchange: 交换机名称
//3. routingKey: 路由键,绑定规则。 如果交换机的类型为fanout,routingKey设置为空
// routingKey 系统的名称.日志的级别
// 所有error级别的日志分发给queue1Name,所有order系统的日志分发给queue1Name
channel.queueBind(queue1Name, exchangeName, "#.error");
channel.queueBind(queue1Name, exchangeName, "order.*");
channel.queueBind(queue2Name, exchangeName, "*.*");
//8.发送消息
String body = "这是一条rabbitmq的error信息哦";
String body1 = "这是一条rabbitmq的order信息哦";
String body2 = "这是一条rabbitmq的info信息哦";
channel.basicPublish(exchangeName, "a.error", null, body.getBytes());
channel.basicPublish(exchangeName, "order.a", null, body1.getBytes());
channel.basicPublish(exchangeName, "info.a", null, body2.getBytes());
//9.释放资源
channel.close();
connection.close();
}
}
消费者1
package org.example.topic;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MyConsumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("47.115.217.235");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("mofeng");//用户名默认guest
factory.setPassword("263327");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
String queenName1 = "test_topic_queue1";
/*
public String basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoACk: 是否自动确认
callback: 回调对象
*/
Consumer consumer = new DefaultConsumer(channel) {
/**
* 回调方法,当收到消息后,会自动执行该方法
* 1.consumerTag: 标识
* 2.envelope: 获取一些信息, 交换机, 路由key...
* 3.properties: 配置信息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
System.out.println("==================================================================");
// System.out.println("consumerTag:" + consumerTag);
// System.out.println("Exchange:" + envelope.getExchange());
// System.out.println("RoutingKey:" + envelope.getRoutingKey());
// System.out.println("properties:" + properties);
System.out.println(queenName1 + ": '执行了'");
System.out.println("body:" + new String(body));
System.out.println("==================================================================");
}
};
channel.basicConsume(queenName1, true, consumer);
}
}
消费者2
package org.example.topic;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MyConsumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2.设置参数
factory.setHost("47.115.217.235");//默认值 localhost
factory.setPort(5672); //端口默认值5672
factory.setVirtualHost("/");//虚拟机默认值 /
factory.setUsername("mofeng");//用户名默认guest
factory.setPassword("263327");//密码默认值guest
//3.创建连接Connection
Connection connection = factory.newConnection();
//4.创建Channel
Channel channel = connection.createChannel();
//5.创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
queue:队列名称
durable:是否持久化,当mq重启之后,还在
exclusive:
是否独占。只能有一个消费者监听这队列
当Connection关闭时,是否册除队列
autoDelete:是否自动地除。 当没有Consumer时,自动删除掉
arguments: 参数。
*/
String queenName2 = "test_topic_queue2";
/*
public String basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoACk: 是否自动确认
callback: 回调对象
*/
Consumer consumer = new DefaultConsumer(channel) {
/**
* 回调方法,当收到消息后,会自动执行该方法
* 1.consumerTag: 标识
* 2.envelope: 获取一些信息, 交换机, 路由key...
* 3.properties: 配置信息
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
System.out.println("==================================================================");
// System.out.println("consumerTag:" + consumerTag);
// System.out.println("Exchange:" + envelope.getExchange());
// System.out.println("RoutingKey:" + envelope.getRoutingKey());
// System.out.println("properties:" + properties);
System.out.println(queenName2 + ": '执行了'");
System.out.println("body:" + new String(body));
System.out.println("==================================================================");
}
};
channel.basicConsume(queenName2, true, consumer);
}
}
JMS 即Java消息服务(JavaMessage Service)应用程序接口,是一个Java平台中关于面向消息中间件的API
JMS 是JavaEE规范中的一种,像JDBC。
很多消息中间件都实现了JMS规范,例如:ActiveMQ。 RabbitMQ 官方没有提供JMS的实现包,但是开源社区有。
官网
docker run -it --rm --name=rabbitmq -p 5672:5672 -p 15672:15672 -v rabbitmq-home:/var/lib/rabbitmq -e RABBITMQ_DEFAULT_USER=xxxx -e RABBITMQ_DEFAULT_PASS=xxxx rabbitmq:3.11-management
RABBITMQ_DEFAULT_USER环境变量:指定RabbitMQ的用户名
RABBITMQ_DEFAULT_PASS环境变量:指定RabbitMQ的密码
版本号带management的,内部集成了一个管理插件,否则就没有。