RocketMQ簡單入門實例

消息隊列優勢


專業&驗證
  1. MQ是消息領域業內專業的消息中間件,多次在國內外獲獎
  2. 經過雙11阿里交易、商品、營銷等核心鏈路真實場景驗證
  3. 阿里集團內部1000+核心應用使用,每天流轉幾千億條消息,穩定可靠
  4. 3種消息發送方式,消息場景全覆蓋:可靠同步、可靠異步、oneway方式
技術體系
  1. 產品歷史超過7年,消息保證不丟,技術體系豐富成熟
  2. 阿里內部產品名:MetaQ、Notify
  3. 開源社區產品名:RocketMQ,無技術綁定風險
  4. 應用靈活,無任何強制綁定其他產品
獨立部署
  1. 支持專有云獨立輸出,支持物理機和虛擬機,最小部署僅幾臺機器
  2. 專有云配套運維繫統,方便運維人員實時監控系統狀態
  3. 專有云配套mqadmin命令集和管理類open API,方便集成及統一運維
  4. 支持混合雲架構,包括VPC用戶
高可靠
  1. 一份消息多份落盤存儲,經過嚴格斷電測試,消息依然保證不丟失
  2. 支持消息軌跡,消息從生產到消費軌跡,可清晰排查
  3. 海量消息堆積,單個Topic可堆積100億+條消息,防止系統高流量崩潰
  4. 默認情況下消息落盤保留3天
高性能
  1. 同一網絡內,消息傳輸RT在10毫秒之內,性能測試下,網卡可被打滿
  2. 公有云默認單Topic 發送消息爲每秒5000條,最高可申請擴展至10W以上, 支持大量消息併發發送,超過5萬個隊列,性能依然卓越
  3. 支持消息海量堆積,單Topic可堆積100+億條消息
  4. 單條消息默認最大支持256K,北京爲4M
多協議
  1. HTTP接入(簡單、免費):HTTP公網接入支持跨網絡調用,無短連接池,不會導致FULL GC,無CPU 100%佔用風險
  2. MQTT接入(物聯、免費):支持主動推送模,多級Topic模型支持一次觸達1000萬+終端, 可廣泛應用於物聯網\社交\娛樂互動場景,支持SSL加密、web socket、flash
  3. TCP接入(專業) :區別於HTTP簡單的接入方式,同時提供更爲專業、可靠、穩定的TCP協議的SDK接入

1.Producer代碼如下:

package com.rocketmq;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.Message;


public class Producer {
public static void main(String[] args) throws MQClientException,
InterruptedException {
/**
* 一個應用創建一個Producer,由應用來維護此對象,可以設置爲全局對象或者單例
* 注意:ProducerGroupName需要由應用來保證唯一
* ProducerGroup這個概念發送普通的消息時,作用不大,但是發送分佈式事務消息時,比較關鍵,
* 因爲服務器會回查這個Group下的任意一個Producer
*/
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("127.0.0.1:80");
/**
* Producer對象在使用之前必須要調用start初始化,初始化一次即可 注意:切記不可以在每次發送消息時,都調用start方法
*/
producer.start();


/**
* 下面這段代碼表明一個Producer對象可以發送多個topic,多個tag的消息。
* 注意:send方法是同步調用,只要不拋異常就標識成功。但是發送成功也可會有多種狀態
* 例如消息寫入Master成功,但是Slave不成功,這種情況消息屬於成功,但是對於個別應用如果對消息可靠性要求極高,
* 需要對這種情況做處理。另外,消息可能會存在發送失敗的情況,失敗重試由應用來處理。
*/
for (int i = 0; i < 10; i++)
try {
{
Message msg = new Message("Topic1",// topic
"TagA",// tag
"001",// key
("Send Msg:Hello MetaQ1").getBytes());// body
SendResult sendResult = producer.send(msg);
System.out.println(sendResult);
}


{
Message msg = new Message("Topic2",// topic
"TagB",// tag
"002",// key
("Send Msg:Hello MetaQ2").getBytes());// body
SendResult sendResult = producer.send(msg);
System.out.println(sendResult);
}


{
Message msg = new Message("Topic3",// topic
"TagC",// tag
"003",// key
("Send Msg:Hello MetaQ3").getBytes());// body
SendResult sendResult = producer.send(msg);
System.out.println(sendResult);
}
} catch (Exception e) {
e.printStackTrace();
}


/**
* 應用退出時,要調用shutdown來清理資源,關閉網絡連接,從MetaQ服務器上註銷自己
* 注意:我們建議應用在JBOSS、Tomcat等容器的退出鉤子裏調用shutdown方法
*/
producer.shutdown();
}
}

2.Customer代碼如下:

package com.rocketmq;
import java.util.List;
import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;
import com.alibaba.rocketmq.common.message.MessageExt;


public class Consumer {

/**
* 當前例子是PushConsumer用法,使用方式給用戶感覺是消息從RocketMQ服務器推到了應用客戶端。
* 但是實際PushConsumer內部是使用長輪詢Pull方式從Broker拉消息,然後再回調用戶Listener方法
*/
public static void main(String[] args) throws InterruptedException,
MQClientException {
/**
* 一個應用創建一個Consumer,由應用來維護此對象,可以設置爲全局對象或者單例
* 注意:ConsumerGroupName需要由應用來保證唯一
*/
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_001");
// consumer.setNamesrvAddr("10.10.0.102:9876");
consumer.setNamesrvAddr("127.0.0.1:80");


/**
* 訂閱指定topic下tags分別等於TagA或TagC或TagD
*/
consumer.subscribe("Topic1", "TagA || TagC || TagD");
/**
* 訂閱指定topic下所有消息<br>
* 注意:一個consumer對象可以訂閱多個topic
*/
consumer.subscribe("Topic2", "*");
consumer.subscribe("Topic3", "*");


/**
* 設置Consumer第一次啓動是從隊列頭部開始消費還是隊列尾部開始消費 如果非第一次啓動,那麼按照上次消費的位置繼續消費
*/
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
consumer.registerMessageListener(new MessageListenerConcurrently() {
/**
* 默認msgs裏只有一條消息,可以通過設置consumeMessageBatchMaxSize參數來批量接收消息
*/
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
System.out.println(Thread.currentThread().getName()
+ " Receive New Messages: " + msgs);


MessageExt msg = msgs.get(0);
if (msg.getTopic().equals("Topic1")) {
if (null != msg.getTags()) {
// 執行Topic1的消費邏輯
if (msg.getTags().equals("TagA")) {
// 執行TagA的消費
System.out.println("TagA開始。");
} else if (msg.getTags().equals("TagC")) {
System.out.println("TagC開始。");
// 執行TagC的消費
} else if (msg.getTags().equals("TagD")) {
// 執行TagD的消費
System.out.println("TagD開始。");
}
}
} else if (msg.getTopic().equals("Topic2")) {
// 執行Topic2的消費邏輯
System.out.println("Topic2");
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
/**
* Consumer對象在使用之前必須要調用start初始化,初始化一次即可
*/
consumer.start();
System.out.println("Consumer Started.");
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章