rabbitmq(三) 消息確認

爲確保發送的消息能夠被消費者處理,rabbitmq提供了消息確認功能,這裏send爲消息生產者,receive爲消息消費者。生產的消息首先會發送到服務器中保存,然後等待消費者處理,所謂消息確認功能,就是消費者在處理完消息後,給服務器發送一個反饋,服務器收到反饋後就會將對應的消息刪除。倘若消費者超時不反饋,那麼服務器就會將消息重新發送給其他消費者,造成了同一消息不停轉發。


rabbitmq默認自動消息確認功能是開啓的,當然我們也可以手動確認。這就需要先關閉自動確認功能,等消費者任務結束後再手動確認。


關閉自動確認

QueueingConsumer consumer = new QueueingConsumer(channel);
boolean autoAck = false;
channel.basicConsume(QUEUE_NAME, autoAck, consumer);<pre name="code" class="java">


接收端確認反饋

import org.apache.log4j.Logger;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

/**
 * @author 作者 : monkey
 * @version 創建時間:2016年2月23日 下午4:53:55
 *          消息接收類
 */
public class Receive2 {
	// 定義queue名稱
	private final static String QUEUE_NAME = "queue_test_1";
	// 設置日誌
	static Logger logger = Logger.getLogger(Receive.class);
	
	public static void start() throws Exception {
		// connection製造工廠
		ConnectionFactory factory = new ConnectionFactory();
		// 由於rabbitmq-server安裝在本機,故用localhost或127.0.0.1
		factory.setHost("localhost");
		// 創建連接
		Connection connection = factory.newConnection();
		// 創建渠道
		Channel channel = connection.createChannel();
		// 定義queue屬性
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		// logger.info("[*] Waiting for messages. To exit press CTRL+C");
		
		// 配置獲取消息方式
		QueueingConsumer consumer = new QueueingConsumer(channel);		
		//取消 自動反饋 
        boolean autoAck = false ; 
		channel.basicConsume(QUEUE_NAME, autoAck, consumer);
		
		// 循環獲取消息
		while (true) { // 若沒有消息,這一步將會一直阻塞
			QueueingConsumer.Delivery delivery = consumer.nextDelivery();
			String message = new String(delivery.getBody());
			//確認消息,已經收到  
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);  
			
			logger.info("[**] Received '" + message + "' from " + QUEUE_NAME);
		}
		
	}
}
消息發送類

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import org.apache.log4j.Logger;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/** 
 * send message
 * @author monkey 
 * 
 */ 

public class Send {//發送端
	 private final static String QUEUE_NAME = "queue_test_1";  
	 static Logger logger = Logger.getLogger(Send.class);
	  
	    public static void start() throws IOException, TimeoutException  
	    {  
	    	//connection製造工廠
	        ConnectionFactory factory = new ConnectionFactory();  
	        //由於rabbitmq-server安裝在本機,故用localhost或127.0.0.1
	        factory.setHost("localhost");  
	        //創建連接
	        Connection connection = factory.newConnection();  
	        //創建渠道
	        Channel channel = connection.createChannel();  
	        //定義queue屬性
	        channel.queueDeclare(QUEUE_NAME, false, false, false, null);  
	        
	        String message = "This is the test message~";  
	        //發送消息  
	        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());  
	      
	        logger.info(" [*] Send '" + message + "' to "+QUEUE_NAME+" success!" );
	  
	        channel.close();  
	        connection.close();  
	    }  
}
結果顯示:

分別運行send和receive類,運行一次send,發送了一個消息到rabbitmq-server中,當第一次運行receive時,接收到了server中的消息並給與服務器反饋,所以在第二次運行receive時,則服務器中沒有消息,故處於等待狀態。若receive類中沒有對接收到的消息進行確認反饋,那麼在第二次運行receive時仍會接收到消息。


另外,如果rabbitmq server突然掛掉,那麼還沒讀取到的消息就會丟失,爲了讓消息持久化,需要在定義Queue時進行設置:

boolean durable = true;
channel.queueDeclare(channelName, durable, false, false, null);


這樣設置後,服務器會將收到的消息立即寫入到硬盤,從而防止服務器突然宕機導致數據丟失。但若服務器剛接收到消息還未來得及寫入到硬盤就宕機了,數據仍然會丟失。

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