------------------------------------------------------------------------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);
}
});
}
}