1.rabbitMQ介紹
rabbitMQ是由erlang語言開發的,基於AMQP協議實現的訊息佇列。他是一種應用程式之間的通訊方法,在分散式系統開發中應用非常廣泛。
rabbitMq的有點:
- 使用簡單,功能強大
- 基於AMQP協議
- 社群活躍,文件完善
- 高併發效能好,erlang語言是專門用於開發高併發程式的
- springBoot預設整合rabbitMq
AMQP(advanced Message Queuing Protocol),是一個提供統一訊息服務的應用標準高階訊息佇列協議,是應用層協議的一個開放標準,為面向訊息的中介軟體設計,基於此協議的客戶端與訊息中介軟體可傳遞訊息,並不受客戶端中介軟體的產品不同和開發語言不同的限制。JMS和AMQP的區別在於:JMS是java語言專屬的訊息服務標準,他是在api層定義標準,並且只能用於java應用,而AMQP是在協議層定義的標準,是可以跨語言的。
2.工作流程
傳送訊息:
- 生產者和broker建立TCP連線
- 生產者和broker建立通道
- 生產者通過通道訊息傳送給broker,由exchange將訊息轉發
- exchange將訊息轉發給指定的queue
接受訊息:
- 消費者和broker建立TCP連線
- 消費者和broker建立通道
- 消費者監聽指定的queue
- 當有訊息到達queue的時候broker預設將訊息推送給消費者
- 消費者接受到訊息並消費
3.安裝
如果不想自己下載,需要我這裡的軟體的,可以在下面評論郵箱,我私發給你。
1.安裝erlang的環境,雙擊otp的執行程式,然後一路點選下一步(next)。
配置環境變數
在path中新增erlang的路徑
2.安裝rabbitMq,雙擊rabbitmq的執行程式
安裝完成之後在選單頁面可以看到
安裝完RabbitMQ如果想要訪問管理頁面需要在rabbitmq的sbin目錄中使用cmd執行:rabbitmq-plugins.bat enable rabbitmq_management(管理員身份執行此命令)新增視覺化外掛。
點選上圖中的start/stop來開啟/停止服務。然後在瀏覽器上輸入地址檢視,rabbitMq的預設埠是15672。預設的使用者名稱和密碼都是guest
如果安裝失敗,需要解除安裝重灌的時候或者出現rabbitMq服務註冊失敗時,此時需要進入登錄檔清理erlang(搜尋rabbitMQ,erlsrv將對應的項刪除)
4.程式碼實現
1.新增依賴
<!--新增rabbitMq的依賴-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.3</version>
</dependency>
2.生產者程式碼實現
package rabbitmq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.net.ConnectException;
import java.util.concurrent.TimeoutException;
/**
* @className: producer
* @description: rabbitmq的生產者程式碼實現
* @author: charon
* @create: 2021-01-03 23:10
*/
public class Producer {
/**
* 宣告佇列名
*/
private static final String QUEUE = "hello charon";
public static void main(String[] args) {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
// 建立通道
channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE, true, false, false, null);
String message = "hello charon good evening";
// 釋出訊息(交換機,RoutingKey即佇列名,額外的訊息屬性,訊息內容)
channel.basicPublish("", QUEUE, null, message.getBytes());
System.out.println("傳送訊息給mq:" + message);
} catch (Exception e) {
e.printStackTrace();
}finally {
// 關閉資源
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.消費者程式碼實現
package rabbitmq;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @className: Consumer
* @description: 消費者的程式碼實現
* @author: charon
* @create: 2021-01-05 08:28
*/
public class Consumer {
/**
* 宣告佇列名
*/
private static final String QUEUE = "hello charon";
public static void main(String[] args) throws IOException, TimeoutException {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE, true, false, false, null);
// 實現消費方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/**
*
* @param consumerTag 消費者標籤
* @param envelope 信封,可以獲取交換機等資訊
* @param properties 訊息屬性
* @param body 消費內容,位元組陣列,可以轉成字串
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
// String exchange = envelope.getExchange();
// long deliveryTag = envelope.getDeliveryTag();
String message = new String(body,"utf-8");
System.out.println("收到的訊息是:"+message);
}
};
// 消費訊息(佇列名,是否自動確認,消費方法)
channel.basicConsume(QUEUE,true,defaultConsumer);
}
}
5.rabbitMq的工作模式
- Work queues 工作佇列(資源競爭)
生產者將訊息放入到佇列中,消費者可以有多個,同時監聽同一個佇列。如上圖,消費者c1,c2共同爭搶當前訊息佇列的內容,誰先拿到誰負責消費訊息,缺點是在高併發的情況下,預設會產品一個訊息被多個消費者共同使用,可以設定一個鎖開關,保證一條訊息只能被一個消費者使用。
上面的程式碼,可以再新增一個消費者,這樣就可以實現工作佇列的工作模式。
2.Publish/Subscribe 釋出訂閱(共享資源)
X代表rabbitMq內部元件交換機,生產者將訊息放入交換機,交換機發布訂閱把訊息傳送到所有訊息佇列中,對應的消費者拿到訊息進行消費,對比工作佇列而言,釋出訂閱可以實現工作佇列的功能,但是比工作佇列更強大。
特點:
1.每個消費者監聽自己的佇列
2.生產者將訊息傳送給Broker,由交換機將訊息轉發到繫結的此交換機的每個佇列,每個繫結交換機的佇列都將接收到訊息;
生產者:
package rabbitmq.publish;
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;
/**
* @className: Producer
* @description: 釋出訂閱的生產者
* @author: charon
* @create: 2021-01-07 22:02
*/
public class Producer {
/**郵件的佇列*/
public static final String QUEUE_INFORM_EMAIL = "queue_inform_email";
/**簡訊的佇列*/
public static final String QUEUE_INFORM_SMS = "queue_inform_sms";
/**交換機*/
public static final String EXCHANGE_FANOUT_INFORM = "exchange_fanout_inform";
public static void main(String[] args) {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
// 建立通道
channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);
channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);
// 交換機(交換機名稱,交換機型別(fanout:釋出訂閱,direct:routing,topic:主題,headers:header模式))
channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);
// 繫結交換機(佇列名稱,交換機名稱,routingKey(釋出訂閱設定為空))
channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_FANOUT_INFORM,"");
channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_FANOUT_INFORM,"");
// 傳送多條訊息
for (int i = 0; i < 5; i++) {
String message = "hello charon good evening by publish";
// 指定交換機(交換機,RoutingKey即佇列名,額外的訊息屬性,訊息內容)
channel.basicPublish(EXCHANGE_FANOUT_INFORM, "", null, message.getBytes());
System.out.println("傳送訊息給mq:" + message);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 關閉資源
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
消費email的消費者:
package rabbitmq.publish;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @className: EmailConsumer
* @description: 郵件的訊息消費者
* @author: charon
* @create: 2021-01-07 22:14
*/
public class EmailConsumer {
/**郵件的佇列*/
public static final String QUEUE_INFORM_EMAIL = "queue_inform_email";
/**簡訊的佇列*/
public static final String QUEUE_INFORM_SMS = "queue_inform_sms";
/**交換機*/
public static final String EXCHANGE_FANOUT_INFORM = "exchange_fanout_inform";
public static void main(String[] args) throws IOException, TimeoutException {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);
channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);
channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);
// 實現消費方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/**
*
* @param consumerTag 消費者標籤
* @param envelope 信封,可以獲取交換機等資訊
* @param properties 訊息屬性
* @param body 消費內容,位元組陣列,可以轉成字串
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
// String exchange = envelope.getExchange();
// long deliveryTag = envelope.getDeliveryTag();
String message = new String(body,"utf-8");
System.out.println("收到的email訊息是:"+message);
}
};
// 消費訊息(佇列名,是否自動確認,消費方法)
channel.basicConsume(QUEUE_INFORM_EMAIL,true,defaultConsumer);
}
}
消費簡訊的消費者:
package rabbitmq.publish;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @className: SmsConsumer
* @description:
* @author: charon
* @create: 2021-01-07 22:17
*/
public class SmsConsumer {
/**郵件的佇列*/
public static final String QUEUE_INFORM_EMAIL = "queue_inform_email";
/**簡訊的佇列*/
public static final String QUEUE_INFORM_SMS = "queue_inform_sms";
/**交換機*/
public static final String EXCHANGE_FANOUT_INFORM = "exchange_fanout_inform";
public static void main(String[] args) throws IOException, TimeoutException {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);
channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);
channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);
// 實現消費方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/**
*
* @param consumerTag 消費者標籤
* @param envelope 信封,可以獲取交換機等資訊
* @param properties 訊息屬性
* @param body 消費內容,位元組陣列,可以轉成字串
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body,"utf-8");
System.out.println("收到的簡訊訊息是:"+message);
}
};
// 消費訊息(佇列名,是否自動確認,消費方法)
channel.basicConsume(QUEUE_INFORM_SMS,true,defaultConsumer);
}
}
3.Routing 路由模式
生產者將訊息傳送給交換機按照路由判斷,交換機根據路由的key,只能匹配上路由key的對應的訊息佇列,對應的消費者才能消費訊息。
如上圖,rabbitMq根據對應的key,將訊息傳送到對應的佇列中,error通知將傳送到amqp.gen-S9b上,由消費者c1消費。error,info,warning通知將傳送到amqp.gen-Ag1上,由消費者c2消費。
特點:
1.每個消費者監聽自己的佇列,並且設定路由key
2.生產者將訊息傳送給交換機,由交換機根據路由key來轉發訊息到指定的佇列
生產者:
package rabbitmq.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;
/**
* @className: Producer
* @description: 路由模式下的生成者
* @author: charon
* @create: 2021-01-07 22:34
*/
public class Producer {
/**郵件的佇列*/
public static final String QUEUE_ROUTING_EMAIL = "queue_routing_email";
/**簡訊的佇列*/
public static final String QUEUE_ROUTING_SMS = "queue_routing_sms";
/**交換機*/
public static final String EXCHANGE_ROUTING_INFORM = "exchange_routing_inform";
/** 設定email的路由key */
public static final String ROUTING_EMAIL = "routing_email";
/** 設定sms的路由key */
public static final String ROUTING_SMS = "routing_sms";
public static void main(String[] args) {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
// 建立通道
channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE_ROUTING_EMAIL, true, false, false, null);
channel.queueDeclare(QUEUE_ROUTING_SMS, true, false, false, null);
// 交換機(交換機名稱,交換機型別(fanout:釋出訂閱,direct:routing,topic:主題,headers:header模式))
channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);
// 繫結交換機(佇列名稱,交換機名稱,routingKey)
channel.queueBind(QUEUE_ROUTING_EMAIL,EXCHANGE_ROUTING_INFORM,ROUTING_EMAIL);
channel.queueBind(QUEUE_ROUTING_SMS,EXCHANGE_ROUTING_INFORM,ROUTING_SMS);
// 傳送多條訊息
for (int i = 0; i < 5; i++) {
String message = "hello charon good evening by routing --email";
// 指定交換機(交換機,RoutingKey,額外的訊息屬性,訊息內容)
channel.basicPublish(EXCHANGE_ROUTING_INFORM, ROUTING_EMAIL, null, message.getBytes());
System.out.println("傳送訊息給mq:" + message);
}
// 傳送多條訊息
for (int i = 0; i < 5; i++) {
String message = "hello charon good evening by routing --sms";
// 指定交換機(交換機,RoutingKey,額外的訊息屬性,訊息內容)
channel.basicPublish(EXCHANGE_ROUTING_INFORM, ROUTING_SMS, null, message.getBytes());
System.out.println("傳送訊息給mq:" + message);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 關閉資源
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
消費email的消費者:
package rabbitmq.routing;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @className: EmailConsumer
* @description: 路由模式下的email消費者
* @author: charon
* @create: 2021-01-07 22:40
*/
public class EmailConsumer {
/**郵件的佇列*/
public static final String QUEUE_ROUTING_EMAIL = "queue_routing_email";
/**交換機*/
public static final String EXCHANGE_ROUTING_INFORM = "exchange_routing_inform";
/** 設定email的路由key */
public static final String ROUTING_EMAIL = "routing_email";
public static void main(String[] args) throws IOException, TimeoutException {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE_ROUTING_EMAIL, true, false, false, null);
channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);
// 繫結佇列並指明路由key
channel.queueBind(QUEUE_ROUTING_EMAIL,EXCHANGE_ROUTING_INFORM,ROUTING_EMAIL);
// 實現消費方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/**
*
* @param consumerTag 消費者標籤
* @param envelope 信封,可以獲取交換機等資訊
* @param properties 訊息屬性
* @param body 消費內容,位元組陣列,可以轉成字串
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body,"utf-8");
System.out.println("收到的email訊息是:"+message);
}
};
// 消費訊息(佇列名,是否自動確認,消費方法)
channel.basicConsume(QUEUE_ROUTING_EMAIL,true,defaultConsumer);
}
}
消費簡訊的消費者:
package rabbitmq.routing;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @className: EmailConsumer
* @description: 路由模式下的email消費者
* @author: charon
* @create: 2021-01-07 22:40
*/
public class SmsConsumer {
/**郵件的佇列*/
public static final String QUEUE_ROUTING_SMS = "queue_routing_sms";
/**交換機*/
public static final String EXCHANGE_ROUTING_INFORM = "exchange_routing_inform";
/** 設定email的路由key */
public static final String ROUTING_SMS = "routing_sms";
public static void main(String[] args) throws IOException, TimeoutException {
// 建立連線工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
// 設定ip,埠,因為是本機,所以直接設定為127.0.0.1
connectionFactory.setHost("127.0.0.1");
// web埠預設為15672,通訊埠為5672
connectionFactory.setPort(5672);
// 設定使用者名稱和密碼
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// 設定虛擬ip,預設為/,一個rabbitmq的服務可以設定多個虛擬機器,每個虛擬機器就相當於一個獨立的mq
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
// 建立通道
Channel channel = connection.createChannel();
// 宣告佇列(佇列名稱,是否持久化,是否排它,是否自動刪除,佇列的擴充套件引數比如設定存活時間等)
channel.queueDeclare(QUEUE_ROUTING_SMS, true, false, false, null);
channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);
// 繫結佇列並指明路由key
channel.queueBind(QUEUE_ROUTING_SMS,EXCHANGE_ROUTING_INFORM,ROUTING_SMS);
// 實現消費方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/**
*
* @param consumerTag 消費者標籤
* @param envelope 信封,可以獲取交換機等資訊
* @param properties 訊息屬性
* @param body 消費內容,位元組陣列,可以轉成字串
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body,"utf-8");
System.out.println("收到的簡訊訊息是:"+message);
}
};
// 消費訊息(佇列名,是否自動確認,消費方法)
channel.basicConsume(QUEUE_ROUTING_SMS,true,defaultConsumer);
}
}
4.Topic 主題模式
- 星號井號代表萬用字元
- 星號代表一個單詞,井號代表一個或多個單詞
- 路由功能新增模糊匹配
- 訊息產生者產生訊息,把訊息交給交換機
- 交換機根據key的規則模糊匹配到對應的佇列,由佇列的監聽消費者接收訊息消費
特點:
1.每個消費者監聽自己的佇列,並且設定帶萬用字元的routingkey
2.生產者將訊息傳送給broker,由交換機及根據路由key來轉發訊息到指定的佇列
5.Header 轉發器
取消了路由key,使用header中的key/value(鍵值對)來匹配佇列。
6.RPC 遠端呼叫
基於direct型別交換機實現。生產者將訊息遠端傳送給rpc佇列,消費者監聽rpc訊息佇列的訊息並訊息,然後將返回結果放入到響應佇列中,生產者監聽響應佇列中的訊息,拿到消費者的處理結果,實現遠端RPC遠端呼叫。
參考檔案:
https://www.cnblogs.com/Jeely/p/10784013.html
https://lovnx.blog.csdn.net/article/details/70991021