RocketMQ概述
RocketMQ是一款由阿里研發的高性能高可靠性的分佈式消息隊列,使用Java語言開發,該項目已經貢獻給了Apache基金會,成爲Apache的頂級開源項目。
在早期,阿里內部使用ActiveMQ作爲其消息傳遞中間件,隨着業務的快速增長,基於ActiveMQ的消息隊列集羣在處理大規模業務吞吐量時會遇到IO等性能瓶頸,阿里研發團隊曾努力優化ActiveMQ,但無奈效果不理想,緊接着他們將目光投向Kafka,不幸的是Kafka並不能滿足他們的要求, 特別是在低延遲和高可靠性方面。在這種情況下,阿里研發團隊最終決定自己研發一個消息隊列引擎來處理更廣泛的使用場景,包括從傳統的發佈/訂閱到大批量高實時、消息零丟失的交易系統。並且將該方案向社區開放,希望可以服務更多的企業。
RocketMQ官方網址:http://rocketmq.apache.org/
目前已經有超過100家企業其業務中使用RocketMQ,下圖是部分使用到RocketMQ的大廠:
下圖是RocketMQ團隊編寫的主流消息隊列對比圖:
消息隊列的優點
簡單來說,消息隊列就是一種“先進先出”的數據結構,框架在此基礎上實現數據傳輸的高性能、消息的高可靠性和系統高可用性,所以在如今微服務大行其道的背景下,分佈式消息隊列可以提供異步、解耦和消峯等功能,已經成爲大型互聯網服務架構裏不可或缺的中間件。
- 異步:在大型電商系統,通常會將各個核心功能拆分成獨立的服務模塊,用戶的下單操作需要多個服務模塊共同完成,如果此時訂單服務要一直等到其他服務的操作完成,那麼整個下單操作耗時將很長,用戶體驗會很差。所以通常的做法就是訂單服務將數據生成後發送到消息隊列之後立刻返回下單成功給用戶,其他依賴服務從消息隊列裏面獲取數據進行延後處理,這種延後的異步功能能夠提升系統的性能和吞吐量,同時不至於讓用戶長時間等待。
- 解耦:很多大型企業裏面通常會有很多的子系統,子系統之間當需要進行消息通訊時,可以通過在子系統之間架設消息隊列,這樣每個子系統只需要關心自己訂閱的數據,子系統之間達到完全解耦,甚至各個子系統實現的語言、技術、架構等等都可以不一樣。
- 消峯:每年的雙十一,淘寶系統都會面臨瞬間大規模流量的衝擊,如果沒有緩衝機制,是不可能支撐得住的。通過利用消息隊列,把大量的用戶請求暫存起來,接着服務依次從隊列裏面將請求取出處理,雖然用戶的請求耗時變長了,但相比較於系統崩潰導致的請求失敗來說,這實際上已經是提高了用戶體驗,並且最重要的是保證了系統的穩定性。
快速使用
1、Linux安裝Java環境
JDK1.8下載地址:https://www.oracle.com/java/technologies/javase-jdk8-downloads.html
作者之前下載的是: jdk-8u211-linux-x64.tar.gz
執行解壓和拷貝:
tar -zxvf jdk-8u211-linux-x64.tar.gz
mv jdk1.8.0_211/ /usr/java1.8/
配置環境變量:
vim /etc/profile
JAVA_HOME=/usr/java1.8
JRE_HOME=/usr/java1.8/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
source /etc/profile
驗證是否安裝成功:
[root@test usr]# java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
2、Linux安裝RocketMQ
RocketMQ下載地址: http://rocketmq.apache.org/dowloading/releases/
作者下載的是:rocketmq-all-4.5.0-bin-release.zip
執行解壓命令:
unzip rocketmq-all-4.5.0-bin-release.zip
配置RocketMQ環境變量
#修改環境變量
vim /etc/profile
export ROCKETMQ_HOME=/home/software/rocketmq-all-4.5.0-bin-release
export PATH=$PATH:$ROCKETMQ_HOME/bin
#更新配置
source /etc/profile
修改JVM配置:修改rocketmq bin目錄下的runserver.sh和runbroker.sh文件
配置指定外網地址:在conf目錄下添加broker.properties文件指定外網地址
防火牆開放三個端口:9876、10911、10909
firewall-cmd --add-port=9876/tcp --permanent
firewall-cmd --add-port=10911/tcp --permanent
firewall-cmd --add-port=10909/tcp --permanent
firewall-cmd --reload
啓動nameServer:
[root@test home]# mqnamesrv -n "192.168.0.149" &
The Name Server boot success. serializeType=JSON
啓動Broker:
[root@test rocketmq-all-4.5.0-bin-release]# mqbroker -n "192.168.0.149:9876" -c conf/broker.properties autoCreateTopicEnable=true &
The broker[DEFAULT_BROKER, 192.168.0.149:10911] boot success. serializeType=JSON and name server is 192.168.0.149:9876
關閉命令
sh bin/mqshutdown broker //停止 broker
sh bin/mqshutdown namesrv //停止 nameserver
3、編寫生產者服務
public class SyncProducer {
public static void main(String[] args) {
try {
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName-1");
producer.setNamesrvAddr("192.168.0.149:9876");
//producer.setSendMsgTimeout(10*1000);
producer.start();
for(int i = 0; i < 100; i++){
Message message = new Message("TopicTest","TagA",
("Hello RocketMQ "+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(message);
System.out.println("sendResult:"+sendResult);
}
producer.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4、編寫消費者服務
public class PushConsumer {
public static void main(String[] args) {
try {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ProducerGroupName-1");
consumer.setNamesrvAddr("192.168.0.149:9876");
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.subscribe("TopicTest","*");
consumer.registerMessageListener((List<MessageExt> msgList,ConsumeConcurrentlyContext consumeConcurrentlyContext) -> {
System.out.printf(Thread.currentThread().getName() + "Receive New Messages :" + msgList + "%n");
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
角色解析
上圖是RocketMQ官方的集羣架構圖,可以看到整體上可以分爲四個角色,分別是:NameServer、Broker、Producer、Consumer。這裏先對它們進行一個簡單介紹,後面會詳細地介紹。
NameServer:
NameServer在消息隊列中起到協調者的作用,Broker啓動時會和NameServer建立長連接。
Broker:
Broker是RocketMQ的核心,通過它可以進行消息的接收、存儲和拉去等功能,生產環境建議配備多臺機器保證Broker的高可用性。
Producer:
消息隊列的生產者,需要與NameServer建立連接,從NameServer獲取Topic路由信息,並向提供Topic服務的Broker Master建立連接。
Consumer:
消息隊列的消費者,同樣與NameServer建立連接,從NameServer獲取Topic路由信息,並向提供Topic服務的Broker Master,Slave建立連接;
安裝Console監控平臺
項目下載地址:https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console
修改配置文件指定NameServer地址:
使用maven打包項目
mvn package -Dmaven.test.skip=true
啓動項目
java -jar rocketmq-console-ng-1.0.0.jar
開放8080端口
[root@test ~]# firewall-cmd --add-port=8080/tcp --permanent
success
[root@test ~]# firewall-cmd --reload
success
訪問監控平臺
http://192.168.0.149:8080