------------------------------------------------------------------------RabbitMq 核心概念-----------------------------------------------------------------------
AMQP:高级消息队列协议
Server :Broker接受客户端的连接,实现AMQP 实体服务
Connection:连接 ,应用程序与Broker 建立连接
Channel:网络通信, 几乎所有的操作都在Channel中进行,是进行消息读写的通道,每一个channel代表一个会话任务
Message:消息,传送的数据 由Properties 和Body 组成
Virtual host:虚拟主机,用于逻辑隔离,最上层的消息路由的划分。同一个Virtual host 不能有相同名称的Exchange或Queue
Exchange :交换机,接受消息,根据路由键转发消息到绑定的队列
Binding: Exchange 和Queue 之间的虚拟连接,bingding中可以包含routing key
Routing key : 一个路由规则,虚拟机可以用它来确定如何路由一个特别消息
Queue : message queue,消息队列
------------------------------------------------------------------------RabbitMq 安装使用-----------------------------------------------------------------------
erlang/socat/rabbitmq
官网下载 erlang(相当于java 的jdk), 和rabbitMq 服务。
配置环境变量后 cmd 执行:
rabbitmqctl status --查看状态
rabbitmq-plugins.bat enable rabbitmq_management //管理界面插件
rabbitmq-server.bat --启动mq 服务
登陆 http://localhost:15672 用户名密码:guest/guest
-----------------------------------------------------------------------命令行操作与管控台-基础操作----------------------------------------------------------
rabbitmqctl stop_app:关闭应用
rabbitmqctl add_user username password: 添加用户
rabbitmqctl list_users: 列出所有用户
rabbitmqctl delete_user username : 删除用户
rabbitmqctl add_vihost vhostpath :创建虚拟主机
rabbitmqctl list_vihost : 列出所有虚拟主机
rabbitmqctl list_queues:查看所有队列信息
rabbitmqctl reset :移除所有数据,要在rabbitmqctl stop_app 之后使用
rabbitmqctl join_cluster <cluster_node> [--ram] : 组成集群命令
rabbitmqctl cluster_status :查看集群状态
....
所有管控台能操作得步骤,控制台命令都可操作。
-----------------------------------------------------------------------Exchange 交换机---------------------------------------------------------------
Exchange有以下属性:
Name:交换机名称
Type:Direct,Topic,Fanout ,Headers(不常用)
Durability:(durable-持久化/transient-瞬变)是否需要持久化,true/durable 为持久化
Auto Delete:当最后一个绑定到Exchange 上得队列删除后,自动删除改Exchange
Internal:当前Exchange是否用于RabbitMQ 内部使用,默认为false/no(基本不做设定使用默认)
Argument:扩展参数,用于扩展AMQP协议自制定化使用
-----------------------------------------------------------------------Direct Exchange 模式---------------------------------------------------------------
Direct Exchange:所有发送到 Direct Exchange 得消息被转发到RoutingKey 中指定得Queue (注意:Direct 模式可以使用RabbitMQ自带得Exchange:default Exchange,所以不需要将Exchange进行任何绑定(binding)操作,消息传递时,Routingkey 必须完全匹配才会被队列接收,否则消息会被抛弃)
/**
* Created by LIUYAO823 on 2019-9-3 15:00
* 生产者
*/
public class Producer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
String Massage = "hello mq test direct exchange";
String exchangename = "test_direct_exchange";
String routingKey = "test_direct";
for (int i = 0; i <5 ; i++) {
//发消息时必须要指定Exchange, 如果没有指定, 默认找default Exchange 通过指定得Routing Key 去找对应得名字
//1.exchange 2.routing key
channel.basicPublish(exchangename,routingKey,null,Massage.getBytes());
}
channel.close();
connection.close();
}
}
/**
* Created by LIUYAO823 on 2019-9-3 15:01
* 消费者
*/
public class Counsumer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
//声明
String exchangename = "test_direct_exchange";
String exchangeType = "direct";
String queuename = "test_direct_queue";
String routingKey = "test_direct";
//声明一个交换机
channel.exchangeDeclare(exchangename,exchangeType,true,false,false,null);
//声明一个队列
channel.queueDeclare(queuename,true,false,false,null);
//交换机和队列通过routingkey绑定
channel.queueBind(queuename,exchangename,routingKey);
//创建一个消费者
channel.basicConsume(queuename, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)
throws IOException
{
System.out.println("消费者......");
//String routingKey = envelope.getRoutingKey();
//String contentType = properties.getContentType();
long deliveryTag = envelope.getDeliveryTag();
channel.basicAck(deliveryTag, false);
}
});
}
}
-----------------------------------------------------------------------Topic Exchange 模式---------------------------------------------------------------
Topic Exchange:所有发送到 Topic Exchange 的消息被转发到所有关心RoutingKey中指定的Topic的Queue上(Exchange 将RoutingKey 和某Topic进行模糊匹配,此时队列需要绑定一个Topic 注意:可以使用通配符进行模糊匹配 "#" 匹配一个或多个词;"*" 匹配不多不少一个词,例如:"log.#" 能够匹配到"log.info.oa" ; "log.*"只会匹配到"log.erro")
/**
* Created by LIUYAO823 on 2019-9-3 15:01
* 消费者
*/
public class Counsumer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
//声明
String exchangename = "test_topic_exchange";
String exchangeType = "topic";
String queuename = "test_topic_queue";
String routingKey = "user.#";
//声明一个交换机
channel.exchangeDeclare(exchangename,exchangeType,true,false,false,null);
//声明一个队列
channel.queueDeclare(queuename,false,false,false,null);
//交换机和队列通过routingkey绑定
channel.queueBind(queuename,exchangename,routingKey);
//创建一个消费者
channel.basicConsume(queuename, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)throws IOException{
System.out.println("消费者consumerTag ["+consumerTag+"]envelope["+envelope+"]properties["+properties+"]");
//String routingKey = envelope.getRoutingKey();
//String contentType = properties.getContentType();
long deliveryTag = envelope.getDeliveryTag();
channel.basicAck(deliveryTag, false);
// System.out.println("消费者收到的消息["++"]");
}
});
}
}
/**
* Created by LIUYAO823 on 2019-9-3 15:00
* 生产者
*/
public class Producer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
String Massage = "hello mq test direct exchange";
String exchangename = "test_topic_exchange";
String routingKey1 = "user.save";
String routingKey2 = "user.update";
String routingKey3 = "user.delete.abc";
System.out.println("生产者......");
channel.basicPublish(exchangename,routingKey1,null,Massage.getBytes());
channel.basicPublish(exchangename,routingKey2,null,Massage.getBytes());
channel.basicPublish(exchangename,routingKey3,null,Massage.getBytes());
channel.close();
connection.close();
}
}
-----------------------------------------------------------------------Fanout Exchange 模式---------------------------------------------------------------
Fanout Exchange:不处理任何的路由键,只需要简单的将队列绑定到交换机上;发送到交换机上的消息都会被转发到与该交换机绑定的所有队列上;Fanout 交换机转发消息是最快的。
/**
* Created by LIUYAO823 on 2019-9-3 15:00
* 生产者
*/
public class Producer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
String Massage = "hello mq test direct exchange";
String exchangename = "test_fanout_exchange";
String routingKey1 = ""; //无论是否设置路由键, fanout模式都忽略,直接看交换机的一个绑定关系
/* String routingKey2 = "user.update";
String routingKey3 = "user.delete.abc";*/
System.out.println("生产者......");
for (int i = 0; i <3 ; i++) {
channel.basicPublish(exchangename,routingKey1,null,Massage.getBytes());
}
channel.close();
connection.close();
}
}
/**
* Created by LIUYAO823 on 2019-9-3 15:01
* 消费者
*/
public class Counsumer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
//声明
String exchangename = "test_fanout_exchange";
String exchangeType = "fanout";
String queuename = "test_fanout_queue";
String routingKey = "";//不设置路由键
//声明一个交换机
channel.exchangeDeclare(exchangename,exchangeType,true,false,false,null);
//声明一个队列
channel.queueDeclare(queuename,false,false,false,null);
//交换机和队列通过routingkey绑定
channel.queueBind(queuename,exchangename,routingKey);
//创建一个消费者
channel.basicConsume(queuename, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)throws IOException{
System.out.println("消费者consumerTag ["+consumerTag+"]envelope["+envelope+"]properties["+properties+"]");
//String routingKey = envelope.getRoutingKey();
//String contentType = properties.getContentType();
long deliveryTag = envelope.getDeliveryTag();
channel.basicAck(deliveryTag, false);
}
});
}
}
-----------------------------------------------------------------------Binding-绑定---------------------------------------------------------------------------------
Binding-绑定: Exchange 和Exchange、Queue之间的连接关系 ; Binding中可以包含RoutingKey或者参数
-----------------------------------------------------------------------Queue-消息队列----------------------------------------------------------------------------Queue-消息队列:实际存储消息数据
Durability:是否需要持久化,durable-是/ transient-否
Auto Delete:当最后一个绑定到Exchange 上得队列删除后,自动删除改Exchange
-----------------------------------------------------------------------Message-消息----------------------------------------------------------------------------
Message:服务和应用程序之间传送的数据;本质上就是一段数据 由Properties 和Body 组成
常用属性:delivery mode、headers(自定义属性)
其它属性:content_type、content_encoding、priority ;
correlation_id、reply_to、expiration、message_id;
timestamp、type、user_id、app_id、cluster_id;
/**
* Created by LIUYAO823 on 2019-9-3 15:00
* 生产者
*/
public class Producer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
String Massage = "hello mq test direct exchange";
String routingKey= "test001";
Map<String, Object> map = new HashMap<>();
map.put("my1","111");
map.put("my2","222");
AMQP.BasicProperties Properties= new AMQP.BasicProperties.Builder()
.deliveryMode(2) //常用模式 2-持久化 服务器重启消息依旧存在
.contentType("UTF-8")//
.expiration("50000") //消息过期时间
.headers(map)//放自定义的属性
.build();
for (int i = 0; i <3 ; i++) {
System.out.println("生产者......");
//发送一个带有附加属性的消息
channel.basicPublish("",routingKey,Properties,Massage.getBytes());
}
channel.close();
connection.close();
}
}
/**
* Created by LIUYAO823 on 2019-9-3 15:01
* 消费者
*/
public class Counsumer {
public static void main(String[] args) throws Exception{
//创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
//通过ConnectionFactory 创建Connection
Connection connection =connectionFactory.newConnection();
//通过Connection创建Channel(核心通信)
Channel channel = connection.createChannel();
//声明
String queuename = "test001";
//声明一个队列
channel.queueDeclare(queuename,true,false,false,null);
//创建一个消费者
channel.basicConsume(queuename, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)throws IOException{
System.out.println("消费者consumerTag ["+consumerTag+"]envelope["+envelope+"]properties["+properties.getHeaders().get("my1")+"]");
//String routingKey = envelope.getRoutingKey();
//String contentType = properties.getContentType();
long deliveryTag = envelope.getDeliveryTag();
channel.basicAck(deliveryTag, false);
}
});
}
}