RocketMQ發送消息的3種方法:
- 可靠同步發送(reliable synchronous)、
- 可靠異步發送(reliable asynchronous)
- 單向發送(one-way transmission)
具體參考RocketMQ官網文檔
可靠同步發送
先創建一個DefaultMQProducer,設 置好GroupName NameServer地址後啓動,然後把待發送的消息拼裝成 Message對象,使用 Producer 發送。
採用同步的方式發送消息到RocketMQ,在重要的消息、需要及時知道發送結果等大多數場景下使用,例如重要的通知消息、短信通知、短信營銷系統等
public class SyncProducer {
public static void main(String[] args) throws Exception {
//Instantiate with a producer group name.
DefaultMQProducer producer = new
DefaultMQProducer("please_rename_unique_group_name");
// Specify name server addresses.
producer.setNamesrvAddr("localhost:9876");
//Launch the instance.
producer.start();
for (int i = 0; i < 100; i++) {
//Create a message instance, specifying topic, tag and message body.
Message msg = new Message("TopicTest" /* Topic */,
"TagA" /* Tag */,
("Hello RocketMQ " +
i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
);
//Call send message to deliver message to one of brokers.
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
}
//Shut down once the producer instance is not longer in use.
producer.shutdown();
}
}
可靠異步發送
異步發送通常被用於對響應時間敏感的業務場景或後臺異步處理的場景,能提高發送的效率和吞吐。採用了future模式,可以在結果回調中處理結果。
public class AsyncProducer {
public static void main(String[] args) throws Exception {
//Instantiate with a producer group name.
DefaultMQProducer producer = new DefaultMQProducer("ExampleProducerGroup");
// Specify name server addresses.
producer.setNamesrvAddr("localhost:9876");
//Launch the instance.
producer.start();
producer.setRetryTimesWhenSendAsyncFailed(0);
for (int i = 0; i < 100; i++) {
final int index = i;
//Create a message instance, specifying topic, tag and message body.
Message msg = new Message("TopicTest",
"TagA",
"OrderID188",
"Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
producer.send(msg, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.printf("%-10d OK %s %n", index,
sendResult.getMsgId());
}
@Override
public void onException(Throwable e) {
System.out.printf("%-10d Exception %s %n", index, e);
e.printStackTrace();
}
});
}
//Shut down once the producer instance is not longer in use.
producer.shutdown();
}
}
單向發送
單向發送用於不要求一定可靠性的場景,例如日誌收集。其發送特點爲只負責發送消息,不等待服務器迴應且沒有回調函數觸發,即只發送請求不等待應答。此方式發送消息的過程耗時非常短。
public class OnewayProducer {
public static void main(String[] args) throws Exception{
//Instantiate with a producer group name.
DefaultMQProducer producer = new DefaultMQProducer("ExampleProducerGroup");
// Specify name server addresses.
producer.setNamesrvAddr("localhost:9876");
//Launch the instance.
producer.start();
for (int i = 0; i < 100; i++) {
//Create a message instance, specifying topic, tag and message body.
Message msg = new Message("TopicTest" /* Topic */,
"TagA" /* Tag */,
("Hello RocketMQ " +
i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
);
//Call send message to deliver message to one of brokers.
producer.sendOneway(msg);
}
//Shut down once the producer instance is not longer in use.
producer.shutdown();
}
}
消費示例
public class Consumer {
public static void main(String[] args) throws InterruptedException, MQClientException {
// Instantiate with specified consumer group name.
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name");
// Specify name server addresses.
consumer.setNamesrvAddr("localhost:9876");
// Subscribe one more more topics to consume.
consumer.subscribe("TopicTest", "*");
// Register callback to execute on arrival of messages fetched from brokers.
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//Launch the consumer instance.
consumer.start();
System.out.printf("Consumer Started.%n");
}
}
更多示例請查看 https://github.com/apache/rocketmq/tree/master/example
如下是rocketMQ的基礎架構圖:
從以上三種發送方式的入門實例中,我們可以看到一些基礎的概念,如生產者、消費者、topic、tag。
- 名稱服務 NameServer cluster
NameServer服務提供了輕量級的服務發現和路由。每個NameServer服務記錄完整的路由信息,提供一致的讀寫服務,支持快速存儲擴展
- 代理服務 Broker Cluster
Broker通過提供輕量級主題和隊列機制來處理消息存儲。它們支持Push和Pull模型,包含容錯機制(2個副本或3個副本),提供了極強的峯值處理裏能力和按照時間順序存儲數以百萬記的消息存儲能力,此外,代理提供了災難恢復、豐富的度量統計和警報機制,這些都是在傳統的消息傳遞系統中缺乏的
- 生產者 Producer Cluster
produce支持分佈式部署,分佈式的produce通過broker集羣提供的各種負載均衡策略將消息發送到broker集羣中。發送過程支持快速失敗是低延遲的。
- 消費者 Consumer Cluster
消費者也支持在推送和者拉取模式下分佈式部署,它還支持集羣消費和消息廣播。提供實時的消息訂閱機制,能夠滿足大多數消費者的需求。RocketMQ的網站爲感興趣的用戶提供了一個簡單的快速入門指南。
- Topic
Topic是生產者在發送消息和消費者在拉取消息的類別。Topic與生產者和消費者之間的關係非常鬆散。具體來說,一個Topic可能有0個,一個或多個生產者向它發送消息;相反,一個生產者可以發送不同類型Topic的消息。類似的,消費者組可以訂閱一個或多個主題,只要該組的實例保持其訂閱一致即可。
RocketMQ的Topic/Queue和JMS中的Topic/Queue概念有一定的差異,JMS中所有消費者都會消費一個Topic消息的副本,而Queue中消息只會被一個消費者消費;但到了RocketMQ中Topic只代表普通的消息隊列,而Queue是組成Topic的更小單元,集羣消費模式下一個消費者只消費該Topic中部分Queue中的消息,當一個消費者開啓廣播模式時則會消費該Topic下所有Queue中的消息。
- Tags
標籤,換句話的意思就是子主題,爲用戶提供了額外的靈活性。有了標籤,來自同一業務模塊的具有不同目的的消息可以具有相同的主題和不同的標記。標籤有助於保持代碼的清晰和連貫,同時標籤也方便RocketMQ提供的查詢過濾功能。Tags的過濾需要經過兩次比對,首先會在Broker端通過Tag hashcode進行一次比對過濾,匹配成功傳到consumer端後再對具體Tags進行比對,以防止Tag hashcode重複的情況。