發送消息的三種方式
同步發送
Producer在進行消息發送時可以是阻塞的,也可以是非阻塞的。具體對應到發送方式一共有三種,分別是同步、異步和單向的(ONEWAY)。之前介紹的調用send()
返回SendResult的方法是阻塞的,它一定要等到Broker進行了響應後纔會返回,才能繼續往下執行。對於下面的代碼就是隻有第一條消息發送完了後,才能發送第二條消息,接着是第三條。這種阻塞發送的方式也叫同步發送,它的整個響應時間還包括可能的重試時間。其內部會默認進行兩次重試,可以通過setRetryTimesWhenSendFailed()
指定同步發送時內部最大的重試次數。
@Test
public void testSyncSend() throws Exception {
//指定Producer的Group爲group1
DefaultMQProducer producer = new DefaultMQProducer("group1");
//指定需要連接的Name Server
producer.setNamesrvAddr(nameServer);
//發送消息前必須調用start(),其內部會進行一些初始化工作。
producer.start();
for (int i = 0; i < 10; i++) {
//指定消息發送的Topic是topic1。
Message message = new Message("topic1", ("hello" + i).getBytes());
//同步發送,發送成功後纔會返回
SendResult sendResult = producer.send(message);
if (sendResult.getSendStatus() == SendStatus.SEND_OK) {
System.out.println("消息發送成功:" + sendResult);
} else {
System.out.println("消息發送失敗:" + sendResult);
}
}
//使用完畢後需要把Producer關閉,以釋放相應的資源
producer.shutdown();
}
異步發送
同步發送時調用send()
的線程會阻塞,而異步發送時當前線程是不會阻塞的。發送結果將由一個回調函數進行回調。下面的代碼就是異步發送消息的示例,它與同步發送消息的區別是它在發送消息時多傳遞了一個SendCallback對象,該方法一調用立馬返回,而不需要等待Broker的響應返回。消息發送成功或失敗後將回調SendCallback對象的對應方法。所以對於下面示例而言,第一條消息Broker還沒有確認發送成功時,第二條消息就發送了,第三條消息也是一樣。它們真正在Broker發送成功的順序其實是不確定的。
@Test
public void sendAsync() throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("group1");
producer.setNamesrvAddr(nameServer);
producer.start();
CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Message message = new Message("topic1", ("send by async, no." + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("發送成功:" + message);
latch.countDown();
}
@Override
public void onException(Throwable throwable) {
System.out.println("發送失敗");
latch.countDown();
}
});
}
latch.await();
producer.shutdown();
}
通過異步方式發送消息如果失敗了,其內部也是會進行重試的,其最大重試次數是通過
setRetryTimesWhenSendAsyncFailed()
指定的,默認也是2次。
ONEWAY
除了同步發送和異步發送外,還有一種發送方式叫ONEWAY,它的發送是單向的,即它不需要等待Broker的響應,只管發送即可,而不論發送成功與失敗。通常應用於一些消息不是那麼重要,可丟失的場景。它的發送是通過調用sendOneway()
發送的。
@Test
public void sendOneway() throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("group1");
producer.setNamesrvAddr(nameServer);
producer.start();
for (int i=0; i<10; i++) {
Message message = new Message("topic1", "tag2", ("message send with oneway, no."+i).getBytes());
producer.sendOneway(message);
}
producer.shutdown();
}
(注:本文是基於Apache RocketMQ4.5.0所寫)