RabbitMQ實戰篇:消息確認之消費者全局確認

上一篇我們已經知道消費者確認消息了,但是如果每個queue都要定義自己的確認信息的話,不免有點累贅,那我們就在一個地方設置一下全局確認信息即可,所以這一篇只告訴你怎麼設置全局,其他代碼請查看上一篇內容

package com.lwl.rabbitmq;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.lwl.rabbitmq.constant.Constants;

/**
 * 
 * 設置全局確認信息
 * 
 * @author lwl
 * @create 2019年6月17日 下午1:34:45
 * @version 1.0
 */
@SpringBootApplication
public class RabbitmqAckApplication {

	public static void main(String[] args) {
		SpringApplication.run(RabbitmqAckApplication.class, args);
	}
	

	   
    /**
     * 自動確認涉及到一個問題就是如果在處理消息的時候拋出異常,消息處理失敗,但是因爲自動確認而導致 Rabbit 將該消息刪除了,造成消息丟失
     * @param connectionFactory
     * @return
     * @author lwl
     * @create 2019年6月17日 上午11:13:14
     */
//    @Bean
//	public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
//	    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
//	    container.setConnectionFactory(connectionFactory);
//	    container.setQueueNames(Constants.TOPIC_QUEUE);                 // 監聽的隊列
//	    container.setAcknowledgeMode(AcknowledgeMode.NONE);     // NONE 代表自動確認
//	    container.setMessageListener((MessageListener) message -> {         //消息監聽處理
//	    	System.out.println();
//	    	System.out.println();
//	    	System.out.println("====接收到消息=====");
//	        System.out.println(new String(message.getBody()));
//	        System.out.println();
//	        System.out.println();
//	        //相當於自己的一些消費邏輯拋錯誤
//	        throw new NullPointerException("consumer fail");
//	    });
//	    return container;
//	}
    /**
     * AcknowledgeMode 除了 NONE 和 MANUAL 之外還有 AUTO ,它會根據方法的執行情況來決定是否確認還是拒絕(是否重新入queue)

		如果消息成功被消費(成功的意思是在消費的過程中沒有拋出異常),則自動確認
		當拋出 AmqpRejectAndDontRequeueException 異常的時候,則消息會被拒絕,且 requeue = false(不重新入隊列)
		當拋出 ImmediateAcknowledgeAmqpException 異常,則消費者會被確認
		其他的異常,則消息會被拒絕,且 requeue = true(如果此時只有一個消費者監聽該隊列,則有發生死循環的風險,多消費端也會造成資源的極大浪費,這個在開發過程中一定要避免的)。可以通過 setDefaultRequeueRejected(默認是true)去設置
     */
    /**
     * 手動確認消息
     * @param connectionFactory
     * @return
     * @author lwl
     * @create 2019年6月17日 下午1:01:43
     */
    @Bean
    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(Constants.TOPIC_QUEUE);              // 監聽的隊列
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);        // 手動確認
        container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {      //消息處理
            System.out.println("====接收到消息=====");
            System.out.println(new String(message.getBody()));
            if(message.getMessageProperties().getHeaders().get("error") == null){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                System.out.println("消息已經確認");
            }else {
                //channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
                System.out.println("消息拒絕");
            }

        });
        return container;
    }
    
    /**
     * AUTO 根據情況確定
     * @param connectionFactory
     * @return
     * @author lwl
     * @create 2019年6月17日 下午1:14:44
     */
//    @Bean
//    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
//        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
//        container.setConnectionFactory(connectionFactory);
//        container.setQueueNames("consumer_queue");              // 監聽的隊列
//        container.setAcknowledgeMode(AcknowledgeMode.AUTO);     // 根據情況確認消息
//        container.setMessageListener((MessageListener) (message) -> {
//            System.out.println("====接收到消息=====");
//            System.out.println(new String(message.getBody()));
//            //拋出NullPointerException異常則重新入隊列
//            //throw new NullPointerException("消息消費失敗");
//            //當拋出的異常是AmqpRejectAndDontRequeueException異常的時候,則消息會被拒絕,且requeue=false
//            //throw new AmqpRejectAndDontRequeueException("消息消費失敗");
//            //當拋出ImmediateAcknowledgeAmqpException異常,則消費者會被確認
//            throw new ImmediateAcknowledgeAmqpException("消息消費失敗");
//        });
//        return container;
//    }
	
}

其他代碼請參考上一篇內容,測試也參考上一篇。

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