消息隊列發佈端性能優化

消息發佈的性能權衡

AMQP規範提供消息發佈中的事務以及消息持久化選項,以提供比自身普通消息發佈更高級別的可靠消息通信機制。
這種可靠消息通信機制,包含投遞確認功能。
投遞確認:該功能提供了不同級別的消息可靠投遞機制,包括跨越多個服務器的高可用性隊列。

rabbitmq的保障機制(要根據業務進行選擇,越往下性能越差)
https://www.jianshu.com/p/cc3d2017e7b3

失敗通知

將 mandatory設置爲true,如果消息不可路由那麼rabbitmq會把完整的消息退回到發佈者中

public RabbitTemplate rabbitTemplate(){
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    template.setMandatory(true); //設置發送消息失敗重試
    return template;
    }

發佈者確認

發佈者確認,即Confirm機制具體的實現方式:
1. 普通的java方法:https://blog.csdn.net/vbirdbest/article/details/78699913
2. 結合springboot的實現方法

第一步:spring.rabbitmq.template.mandatory = true 設置成true
第二步:spring.rabbitmq.publisher-confirms = true 設置成true
第三步:編寫一個 java 類,實現 RabbitTemplate.ConfirmCallback 接口,在這個裏面我們可以確認消息是否到達了RabbitMQ服務器。

這裏RabbitMq提供一個回調函數可以將投遞失敗的消息給輸出出來

// 消息是否從Exchange路由到Queue, 注意: 這是一個失敗回調, 只有消息從Exchange路由到Queue失敗纔會回調這個方法
  rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
         log.info("消息從Exchange路由到Queue失敗: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}", exchange, routingKey, replyCode, replyText, message);
    });

消費者確認

開啓ack應答模式,作爲事務的輕量級替代方法
這種應答模式分爲:自動應答和手動應答
自動應答: 消RabbitMQ可以從隊列中刪除該消息了,可以通過顯示調用channel.basicAck(envelope.getDeliveryTag(), false);來告訴消息服務器來刪除消息費者一收到消息就表示消費者收到了消息,消費者收到了消息就會立即從隊列中刪除。

手動應答: 當消費者收到消息在合適的時候來顯示的進行確認,說我已經接收到了該消息了,RabbitMQ可以從隊列中刪除該消息了,可以通過顯示調用channel.basicAck(envelope.getDeliveryTag(), false);來告訴消息服務器來刪除消息
普通的java: https://blog.csdn.net/vbirdbest/article/details/78699913
springboot項目: https://blog.csdn.net/linpeng_1/article/details/80505828

備用交換器

備用交換器用於處理無法路由的消息。備用交換器在第一次聲明交換器時被指定,用來提供一種預先存在的交換器,即如果交換器無法路由消息,那麼消息就會被路由到這個新的備用交換器。

死信交換器:
過期的消息、basic.nack或basic.reject且requeue參數爲false或隊列滿的消息將進入此交換器

springboot整合rabbitmq實現生產者消息確認、死信交換器、備用交換器的消息處理
https://www.iteye.com/blog/huan1993-2433263

事務

採用AMQP事務機制和發佈者確認的機制,來解決服務器數據丟失的問題。
這種機制極大犧牲了性能從而換取消息的可靠性。
java的實現方式: https://www.cnblogs.com/vipstone/p/9350075.html
springboot的實現方式: https://blog.csdn.net/zhanngle/article/details/86267986

高可用隊列

高可用隊列又稱爲HA隊列,需要RabbitMQ集羣環境,可以通過使用AMQP或者使用基於web的管理界面來設置。
RabbitMQ集羣搭建結合Erlang來實現其內部通信,藉助Haproxy實現請求的負載均衡。
結合springboot實現消息發送的案例: https://blog.csdn.net/zhuyu19911016520/article/details/80206202

基於事務的高可用隊列
在一個集羣的環境下,採用的是事務或投遞確認機制,則消息在被HA隊列定義的所有活動節點確認之後,RabbitMQ纔會發送成功的響應。這種方式會造成很大的延遲。

消息持久化

消息持久化是解決消息被投遞到RabbitMQ的內存中,還沒有投遞到消費者實例之前就宕機了,而導致消息丟失的問題。
解決的實例:將Exchange(交換機,存儲着消息的路由信息)、queue和message都持久化到硬盤,這樣,RabbitMQ重啓時會把持久化的Exchange、queue和message從硬盤重新加載出來,
重新投遞消息。

交換機的持久化
第二個參數durable: 是否持久化, 第三個參數autoDelete: 當所有綁定隊列都不再使用時, 是否自動刪除交換器, true: 刪除, false: 不刪除

@Bean
public DirectExchange logUserExchange() {
    return new DirectExchange("log.user.exchange", true, false);
}

queue的持久化
聲明隊列時指定持久化參數爲true即可

@Bean
public Queue logUserQueue() {
    return new Queue("log.user.queue.name", true);
}

message的持久化
將delivery-mode設置爲2,即可以實現message的持久化。
在默認的情況下message都是持久化的。
下面是發送一個不持久化的message

/**
* 推送一個非持久化的消息,這個消息推送到持久化的隊列時,mq重啓,這個消息會丟失;上面的持久化消息不會丟失
*
* @param ans
* @return
*/private String publish2mq2(String ans) {
    MessageProperties properties = new MessageProperties();
    properties.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);
    Message message = rabbitTemplate.getMessageConverter().toMessage("NonDurable = " + ans, properties);
    rabbitTemplate.convertAndSend(MqConstants.exchange, MqConstants.routing, message);
    System.out.println("publish: " + message);
    return message.toString();}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章