使用AMPQ client 客戶端直接操作,目前框架不是spring的 所以一些常用功能自己封裝
目錄
學習途徑:https://blog.csdn.net/vbirdbest/column/info/18247
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.3</version>
</dependency>
學習途徑:https://blog.csdn.net/vbirdbest/column/info/18247
https://www.cnblogs.com/bluesummer/p/8992225.html
總結
2. 發佈模式
topics:
- 模糊匹配,通過字母配合符號“*”(一個單詞)和“#”(多個單詞)來設置路由鍵
- 相同交換機,相同的隊列,加入多個路由KEY時 消費端可以通過模糊匹配進路由key獲取需要的隊列數據,不匹配默認獲取全部
headers:
- 以消費端爲主要 去匹配 服務器發佈的headers。服務器可以多發,但是消費端匹配到的一個都不能少。
fanout:
- 忽略路由鍵,給所有綁定到交換機上的隊列都發送消息,俗稱廣播
direct:
- 要求路由鍵完全匹配
3. 消息屬性Properties
- content_type : 消息內容的類型 [常用 ]
- content_encoding: 消息內容的編碼格式
- priority: 消息的優先級 根據發佈的時消息的重要性
- correlation_id:關聯id
- reply_to: 用於指定回覆的隊列的名稱 -> RPC 遠程調用時回覆是可以帶上[常用 ]
- expiration: 消息的失效時間
- message_id: 消息id 擁有確認消息之間是否是同一個,用來消息的回覆[常用 ]
- timestamp:消息的時間戳
- type: 類型
- user_id: 用戶id
-
app_id: 應用程序id一般模塊名稱[常用 ]
- cluster_id: 集羣id
4. 消息確認機制
可以自動確認,一收到消息就通知隊列刪除此消息
可以手動確認,一般和業務邏輯是同一個事務提交 來避免網絡導致的無法確認。
5. 隊列聲明
隊列聲明可以設置持久化,持久化即使服務斷開後不會丟失消息
隊列聲明可以設置無消息是否刪除,一般不用
重要參數:
arguments:
Message TTL(x-message-ttl):設置隊列中的所有消息的生存週期(統一爲整個隊列的所有消息設置生命週期), 也可以在發佈消息的時候單獨爲某個消息指定剩餘生存時間,單位毫秒, 類似於redis中的ttl,生存時間到了,消息會被從隊裏中刪除,注意是消息被刪除,而不是隊列被刪除, 特性Features=TTL, 單獨爲某條消息設置過期時間AMQP.BasicProperties.Builder properties = new AMQP.BasicProperties().builder().expiration(“6000”);
channel.basicPublish(EXCHANGE_NAME, “”, properties.build(), message.getBytes(“UTF-8”));
Auto Expire(x-expires): 當隊列在指定的時間沒有被訪問(consume, basicGet, queueDeclare…)就會被刪除,Features=Exp
Dead letter exchange(x-dead-letter-exchange): 當隊列消息長度大於最大長度、或者過期的等,將從隊列中刪除的消息推送到指定的交換機中去而不是丟棄掉,Features=DLX
Dead letter routing key(x-dead-letter-routing-key):將刪除的消息推送到指定交換機的指定路由鍵的隊列中去, Feature=DLK
Maximum priority(x-max-priority):優先級隊列,聲明隊列時先定義最大優先級值(定義最大值一般不要太大),在發佈消息的時候指定該消息的優先級, 優先級更高(數值更大的)的消息先被消費
原文:https://blog.csdn.net/vbirdbest/article/details/78670550
6. 死信交換機
- 一般在發佈消息的時候聲明死信交換機的路徑
- 在隊列聲明中配置
- Dead letter exchange(x-dead-letter-exchange): 當隊列消息長度大於最大長度、或者過期的等,將從隊列中刪除的消息推送到指定的交換機中去而不是丟棄掉,Features=DLX
- Dead letter routing key(x-dead-letter-routing-key):將刪除的消息推送到指定交換機的指定路由鍵的隊列中去, Feature=DLK
- 如果消息處理過程中 方法體或者程序校驗不通過,可以使用死信隊列 人工干預從新處理。
- 消費端使用Nack 來告訴服務器這個消息 請轉發給死信交換機
channel.basicNack(envelope.getDeliveryTag(), false,false);// 程序無法處理 死信隊列
一般發佈者的發佈設置比較總要
/**
* 根據參數發佈消息
* @param appId 當前應用模塊名稱
* @param message 正常隊列名稱
* @param exchangeName 隊列交換機
* @param exchangeType 交換機類型
* @param routingKey 隊列路由
* @param queueName 隊列名稱
* @param isDeadLetter 是否使用死信隊列
* @param dlxExchangeName 死信交換機
* @param dlxExchangeType 死信交換機類型
* @param dlxQueueName 死信隊列名稱
* @return 返回消息是否發佈成功
* @throws Exception
*/
public static boolean publishMessage(String appId,String message,String exchangeName,String exchangeType,String routingKey,String queueName,Boolean isDeadLetter,String dlxExchangeName,String dlxExchangeType,String dlxQueueName,String dlxRoutingKey) throws Exception{
Connection connection = null;
Channel channel = null;
try {
RabbitMqProperties mqProperties = new RabbitMqProperties(new Properties());
// 新建一個長連接
connection = mqProperties.getFactory().newConnection();
// 創建一個通道(一個輕量級的連接)
channel = connection.createChannel();
Map<String, Object> arguments = null;
if(isDeadLetter){
/**
* 死信隊列配置 ----------------
*/
// 創建死信交換器和隊列
channel.exchangeDeclare(dlxExchangeName, dlxExchangeType, true, false, null);
channel.queueDeclare(dlxQueueName, true, false, false, null);
channel.queueBind(dlxQueueName, dlxExchangeName, dlxRoutingKey);
arguments = new HashMap<String, Object>();
// 爲隊列設置隊列交換器
arguments.put("x-dead-letter-exchange",dlxExchangeName);
// 設置交換機的路由key
arguments.put("x-dead-letter-routing-key", dlxRoutingKey);
}
/**
* 正常隊列
*/
// 交換機的創建
channel.exchangeDeclare(exchangeName, exchangeType, true, false, null);
//創建一個持久化、非排他的、非自動刪除的隊列
channel.queueDeclare(queueName, true, false,false,arguments);
//將交換器與隊列通過路由鍵綁定
channel.queueBind(queueName, exchangeName, routingKey);
// 開啓發送方確認模式
channel.confirmSelect();
// 發送消息到隊列中
// 注意:exchange如果不需要寫成空字符串,routingKey和隊列名稱保持一致
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder().appId(appId).contentType(DictUtils.CONTENT_TYPE_TEXT).build();
channel.basicPublish(exchangeName, routingKey, properties, message.getBytes("UTF-8"));
return channel.waitForConfirms();
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
} finally {
if (channel != null) {
channel.close();
}
if (connection != null) {
connection.close();
}
}
}
如果有任何的出錯,希望能指正!感謝