结构图:
介绍:
Broker:接收和分发消息的应用,RabbitMQ Server就是 Message Broker
Virtual host:出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQ server 提供的服务时,可以划分出多个vhost,每个用户在自己的 vhost 创建 exchange/queue 等
Connection:publisher/consumer 和 broker 之间的 TCP 连接
Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的 channel 进行通讯,AMQP method 包含了channel id 帮助客户端和message broker 识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)
Queue:消息最终被送到这里等待 consumer 取走
Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key。Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据
一:rabbitMQ的模式
(1) 简单模式
代码实现(maven工程)
结构:
pom结构:
在父模板中的pom.xml文件中引入依赖
<!--amqp-client 依赖-->
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.10.0</version>
</dependency>
</dependencies>
生产者代码:
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//到的连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//宣告队列
/**
* queue:队列的队列的名称
* druable:如果我们声明一个持久队列(该队列在服务器重启后幸存下来)
* exclusive:如果我们声明一个独占队列,则为true(仅限此连接)
* autodelete:如果我们声明一个自动删除队列,则为true(服务器将在不再使用它时将其删除)
* arguments:队列的其他属性(构造参数) 暂设为null
*/
channel.queueDeclare("哈哈哈",true,false,false,null);
//发布消息
/**
* exchange:将消息发布到的交易所(认为交换机)
* routingKey:路由key 如果没有交换机的绑定 使用队列的名称
* props:消息的其他属性-路由标头等
* byte[] body:邮件正文(消息体)
*/
String msg = "Hello triple H";
channel.basicPublish("","哈哈哈",null,msg.getBytes());
}
消费者代码:
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//到的连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel){
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:"+new String(body));
}
};
//消费者消费
/**
* queue:队列名
* callback:消费者对象的接口
*/
channel.basicConsume("哈哈哈",callback);
}
工作者模式
特点:
1. 一个生产者
2. 由多个消费。
3. 统一个队列。
4. 这些消费者之间存在竞争关系。
生产者:
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//到的连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//宣告队列
/**
* queue:队列的队列的名称
* druable:如果我们声明一个持久队列(该队列在服务器重启后幸存下来)
* exclusive:如果我们声明一个独占队列,则为true(仅限此连接)
* autodelete:如果我们声明一个自动删除队列,则为true(服务器将在不再使用它时将其删除)
* arguments:队列的其他属性(构造参数) 暂设为null
*/
channel.queueDeclare("queue_work",true,false,false,null);
//发布消息
/**
* exchange:将消息发布到的交易所(认为交换机)
* routingKey:路由key 如果没有交换机的绑定 使用队列的名称
* props:消息的其他属性-路由标头等
* byte[] body:邮件正文(消息体)
*/
for (int i=0;i<10;i++){
String msg = "Ganin、red flowers"+i;
channel.basicPublish("","queue_work",null,msg.getBytes());
}
channel.close();
connection.close();
}
消费者01
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_work",true,callback);
}
消费者02
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel){
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:"+new String(body));
}
};
//消费者消费
/**
* queue:队列名
* callback:消费者对象的接口
*/
channel.basicConsume("queue_work",true,callback);
}
发布订阅模式
特点:
1.一个生产者
2.多个消费者
3.多个队列。
4.交换机 转发消息。
生产者代码:
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//到的连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//交易所
/**
* String exchange:交易所名字
* BuiltinExchangeType type :交易类型
* boolean durable :如果我们声明持久交换,则为true(该交换将在服务器重新启动后继续存在)
*/
channel.exchangeDeclare("fanout", BuiltinExchangeType.FANOUT,true);
//宣告队列
/**
* queue:队列的队列的名称
* druable:如果我们声明一个持久队列(该队列在服务器重启后幸存下来)
* exclusive:如果我们声明一个独占队列,则为true(仅限此连接)
* autodelete:如果我们声明一个自动删除队列,则为true(服务器将在不再使用它时将其删除)
* arguments:队列的其他属性(构造参数) 暂设为null
*/
channel.queueDeclare("queue_fanout01",true,false,false,null);
channel.queueDeclare("queue_fanout02",true,false,false,null);
//交易所和队列连接
channel.queueBind("queue_fanout01","fanout","");
channel.queueBind("queue_fanout02","fanout","");
//发布消息
/**
* exchange:将消息发布到的交易所(认为交换机)
* routingKey:路由key 如果没有交换机的绑定 使用队列的名称
* props:消息的其他属性-路由标头等
* byte[] body:邮件正文(消息体)
*/
for (int i=0;i<10;i++){
String msg = "red flowers"+i;
channel.basicPublish("fanout","",null,msg.getBytes());
}
//释放资源
channel.close();
connection.close();
}
消费者01
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_fanout01",true,callback);
}
消费者02
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_fanout02",true,callback);
}
路由模式
特点:
1.一个生产者
2.多个消费者
3.多个队列。
4.交换机 转发消息。
5.routekey:路由key 只要routekey匹配的消息可以到达对应队列。
生产者代码:
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//到的连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//交易所
/**
* String exchange:交易所名字
* BuiltinExchangeType type :交易类型
* boolean durable :如果我们声明持久交换,则为true(该交换将在服务器重新启动后继续存在)
*/
channel.exchangeDeclare("direct", BuiltinExchangeType.DIRECT,true);
//宣告队列
/**
* queue:队列的队列的名称
* druable:如果我们声明一个持久队列(该队列在服务器重启后幸存下来)
* exclusive:如果我们声明一个独占队列,则为true(仅限此连接)
* autodelete:如果我们声明一个自动删除队列,则为true(服务器将在不再使用它时将其删除)
* arguments:队列的其他属性(构造参数) 暂设为null
*/
channel.queueDeclare("queue_direct01",true,false,false,null);
channel.queueDeclare("queue_direct02",true,false,false,null);
//交易所和队列连接
channel.queueBind("queue_direct01","direct","error");
channel.queueBind("queue_direct02","direct","info");
channel.queueBind("queue_direct02","direct","error");
channel.queueBind("queue_direct02","direct","warning");
//发布消息
/**
* exchange:将消息发布到的交易所(认为交换机)
* routingKey:路由key 如果没有交换机的绑定 使用队列的名称
* props:消息的其他属性-路由标头等
* byte[] body:邮件正文(消息体)
*/
for (int i=0;i<10;i++){
String msg = "red flowers"+i;
channel.basicPublish("direct","error",null,msg.getBytes());
}
//释放资源
channel.close();
connection.close();
}
消费者01代码
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_direct01",true,callback);
}
消费者02
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_direct02",true,callback);
}
topic主题模式
1. 绑定按照通配符的模式。
*: 统配一个单词。
#: 统配n个单词
生产者代码:
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//到的连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//交易所
/**
* String exchange:交易所名字
* BuiltinExchangeType type :交易类型
* boolean durable :如果我们声明持久交换,则为true(该交换将在服务器重新启动后继续存在)
*/
channel.exchangeDeclare("topic", BuiltinExchangeType.TOPIC,true);
//宣告队列
/**
* queue:队列的队列的名称
* druable:如果我们声明一个持久队列(该队列在服务器重启后幸存下来)
* exclusive:如果我们声明一个独占队列,则为true(仅限此连接)
* autodelete:如果我们声明一个自动删除队列,则为true(服务器将在不再使用它时将其删除)
* arguments:队列的其他属性(构造参数) 暂设为null
*/
channel.queueDeclare("queue_topic01",true,false,false,null);
channel.queueDeclare("queue_topic02",true,false,false,null);
//交易所和队列连接
channel.queueBind("queue_topic01","topic","*.orange.*");
channel.queueBind("queue_topic02","topic","*.*.rabbit");
channel.queueBind("queue_topic02","topic","lazy.#");
//发布消息
/**
* exchange:将消息发布到的交易所(认为交换机)
* routingKey:路由key 如果没有交换机的绑定 使用队列的名称
* props:消息的其他属性-路由标头等
* byte[] body:邮件正文(消息体)
*/
for (int i=0;i<10;i++){
String msg = "red flowers-->"+i;
channel.basicPublish("topic","lazy.orange.rabbit",null,msg.getBytes());
}
//释放资源
channel.close();
connection.close();
}
消费者01
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_topic01",true,callback);
}
消费者02
public static void main(String[] args) throws Exception {
//创建连接工厂 配置连接信息host
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.31.55");
//获取连接对象
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//消费者
DefaultConsumer callback = new DefaultConsumer(channel) {
@Override // 处理交货 拿到内容信息
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("信息:" + new String(body));
}
};
//消费者消费
/**
* queue:队列名
* autoAck
* callback:消费者对象的接口
*/
channel.basicConsume("queue_topic02",true,callback);
}