爲確保發送的消息能夠被消費者處理,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);
這樣設置後,服務器會將收到的消息立即寫入到硬盤,從而防止服務器突然宕機導致數據丟失。但若服務器剛接收到消息還未來得及寫入到硬盤就宕機了,數據仍然會丟失。