RabbitMQ消息發佈之備用交換器

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


這裏我們直接用代碼來看,首先我們先來看看消息的生產者,如下:

public class DirectProducer {

    //交換器名稱
    public static final String EXCHANGE_NAME = "logs";
    public static final String BACKUP_EXCHANGE_NAME = "backup";

    public static void main(String[] args) throws Exception {
        //創建連接,連接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        Connection connection = connectionFactory.newConnection();

        //創建信道
        Channel channel = connection.createChannel();

        //聲明備用交換器
        Map<String,Object> argsMap = new HashMap<>();
        argsMap.put("alternate-exchange",BACKUP_EXCHANGE_NAME);

        //創建主交換器
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT,false,false,argsMap);
        //創建備用交換器
        channel.exchangeDeclare(BACKUP_EXCHANGE_NAME, BuiltinExchangeType.FANOUT, true, false, null);

        //定義的業務日誌消息級別,即作爲路由鍵使用
        String[] logLevels = {"error", "warn", "info"};
        for (int i = 0; i < logLevels.length; i++) {
            String logLevel = logLevels[i];
            String msg = "Hello RabbitMQ";

            //發佈消息,需要參數:交換器、路由鍵,其中以日誌消息級別爲路由鍵
            channel.basicPublish(EXCHANGE_NAME, logLevel, null, msg.getBytes(Charset.forName("UTF-8")));
        }
        Thread.sleep(2000);
        channel.close();
        connection.close();
    }
}

上述和我們之前的代碼有所不同的就是其中設置了備用交換器,備用交換器一般都是設置FANOUT模式
在這裏插入圖片描述


其中消息的生產者發送了error、warn、info三種路由鍵消息,然後我們再看看消息的消費者,這裏消息的消費者只能路由到error的消息,如下:

public class ErrorConsumer {

    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        //創建連接,連接到RabbitMQ,與發送端一樣
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        Connection connection = connectionFactory.newConnection();
        

        //創建信道
        Channel channel = connection.createChannel();
        //可不創建,由生產者進行創建
        //channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, false, false, null);

        String queueName = "logError";  //聲明一個隊列名稱
        String routingKey = "error";    //路由鍵名稱

        //創建一個隊列
        channel.queueDeclare(queueName, false, false, false, null);
        //將隊列和交換器通過路由鍵進行綁定
        channel.queueBind(queueName, EXCHANGE_NAME, routingKey);

        //聲明瞭一個消費者
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = "Exchange: " + envelope.getExchange() + ", " +
                        "RoutingKey: " + envelope.getRoutingKey() + ", " +
                        "Content: " + new String(body, "UTF-8");
                System.out.println(message);
            }
        };
        //消費者正式開始在指定隊列上消費消息
        channel.basicConsume(queueName, true, consumer);
    }
}

注意: 可以仔細看一下上述消費者代碼,這裏我們把消費者中創建交換器的那一行代碼註釋掉了,這裏是爲什麼呢,因爲我們在消息的生成者中,已經創建過一次該交換器了,如果這裏再創建的話,其參數必須保持一致,否則就會報錯,如下:
在這裏插入圖片描述


如果想要創建,可需要同一交換器在不同的地方進行創建時,其參數需要完全一致,如下:
在這裏插入圖片描述

如上,這樣我們就必須把生產者設置備用交換器的給複製過來,以用於保證其參數的一致性,所以這裏一般就索性直接將其註釋,不創建交換器了,但是這裏註釋掉也會有點小問題,就是我們在第一次如果先啓動該消費者也會報錯,需要先啓動下的消息生產者纔可,因爲我們需要創建交換器呀。



上述完成後,我們消息生產者發送了error、warn、info三種消息,但是消息的消費者只能消費erro消息,那麼其warn、info這兩個消息主交換器就無法進行路由,那麼就會被路由到備用交換器,其備用交換器如下:

public class BackupConsumer {

    public static final String EXCHANGE_NAME = "backup";

    public static void main(String[] args) throws Exception {
        //創建連接,連接到RabbitMQ,與發送端一樣
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        Connection connection = connectionFactory.newConnection();

        //創建信道
        Channel channel = connection.createChannel();
        //綁定交換器
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT,true,false,null);

        //創建一個隨機隊列
        String queueName = channel.queueDeclare().getQueue();

        //將隊列和交換器通過路由鍵進行綁定
        channel.queueBind(queueName, EXCHANGE_NAME, "#");

        //聲明瞭一個消費者
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = "Exchange: " + envelope.getExchange() + ", " +
                        "RoutingKey: " + envelope.getRoutingKey() + ", " +
                        "Content: " + new String(body, "UTF-8");
                System.out.println(message);
            }
        };
        //消費者正式開始在指定隊列上消費消息
        channel.basicConsume(queueName, true, consumer);
    }
}

在其備用交換器中,我們一般定義爲FANOUT模式,然後定義了一個路由鍵#,讓其消費者來接受這些無法路由的消息進行相關的處理。


其測試結果如下:
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章