目錄
- Rocketmq基礎組件講解
- Rocketmq安裝
- Rocketmq圖形化界面安裝與使用
- Springboot與RocketMq的整合
- Rocketmq主從模式搭建
Rocketmq基礎組件講解
Apache RocketMQ作爲阿里開源的一款高性能,高吞吐量的分佈式消息中間件
Rocketmq作爲阿里主推的消息隊列擁有以下特點:
支持Broker和Consumer端消息過濾 |
---|
支持發佈訂閱和點對點 |
支持pull拉和push推兩種消息模式 |
單一隊列億級消息堆積 |
支持單master節點,多master節點,多master和多slave節點 |
任意一個節點都是高可用,水平擴展,Producer,Consumer,Queue都可以分佈式 |
消息失敗重試機制,支持特定Level的定時消息 |
底層採用netty |
4.3.x以後支持分佈式事務 |
適合金融業務,高可用性跟蹤和審計功能 |
Rocketmq節點的說明:
Producer | 消息生產者 |
---|---|
Producer Group | 消息生產組,發送同類消息的一個消息生產組 |
Consumer | 消費者 |
Consumer Group | 消費同類消息的多個實例 |
Tag | 子主題,對topic近一步細化,用於區分同一主題下的不同業務的消息 |
Topic | 主題:訂單類消息主題,新聞類消息主題,是一個邏輯管理單位·,一個topic可以有多個queue,默認創建是4個手動創建是8個 |
Message | 每個消息必須指定一個Topic |
Broker | MQ程序,接收生產者的消息,提供給消費者的程序 |
Name Server | 給生產者和消費者提供路由信息,可以理解爲註冊中心 |
Offset | 偏移量,可以理解爲消息的進度 |
Commit Log | 消息存儲會寫在Commit Log文件裏 |
Rocketmq安裝
本文參照官網安裝手冊:http://rocketmq.apache.org/docs/quick-start/
下載安裝包:https://archive.apache.org/dist/rocketmq/4.7.0/rocketmq-all-4.7.0-source-release.zip
先決條件:
1.jdk安裝 https://blog.csdn.net/gcxzflgl/article/details/106373435
2.maven安裝 https://blog.csdn.net/qq_38270106/article/details/97764483
安裝過程:
1.下載4.7.0版本的安裝壓縮包
wget https://archive.apache.org/dist/rocketmq/4.7.0/rocketmq-all-4.7.0-source-release.zip
2.解壓包 tar -zxvf rocketmq-all-4.7.0-source-release.zip -C ../module/
3.進入解壓後目錄 進行 maven編譯,初次編譯時間較長,可以打兩盤王者再回來
cd rocketmq-all-4.7.0-source-release/
mvn -Prelease-all -DskipTests clean install -U
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Apache RocketMQ 4.7.0 4.7.0:
[INFO]
[INFO] Apache RocketMQ 4.7.0 .............................. SUCCESS [25:15 min]
[INFO] rocketmq-logging 4.7.0 ............................. SUCCESS [02:53 min]
[INFO] rocketmq-remoting 4.7.0 ............................ SUCCESS [04:06 min]
[INFO] rocketmq-common 4.7.0 .............................. SUCCESS [ 55.674 s]
[INFO] rocketmq-client 4.7.0 .............................. SUCCESS [01:43 min]
[INFO] rocketmq-store 4.7.0 ............................... SUCCESS [01:39 min]
[INFO] rocketmq-srvutil 4.7.0 ............................. SUCCESS [ 0.318 s]
[INFO] rocketmq-filter 4.7.0 .............................. SUCCESS [03:15 min]
[INFO] rocketmq-acl 4.7.0 ................................. SUCCESS [ 46.760 s]
[INFO] rocketmq-broker 4.7.0 .............................. SUCCESS [ 2.588 s]
[INFO] rocketmq-tools 4.7.0 ............................... SUCCESS [ 1.571 s]
[INFO] rocketmq-namesrv 4.7.0 ............................. SUCCESS [ 0.634 s]
[INFO] rocketmq-logappender 4.7.0 ......................... SUCCESS [01:03 min]
[INFO] rocketmq-openmessaging 4.7.0 ....................... SUCCESS [ 7.243 s]
[INFO] rocketmq-example 4.7.0 ............................. SUCCESS [ 0.726 s]
[INFO] rocketmq-test 4.7.0 ................................ SUCCESS [ 30.650 s]
[INFO] rocketmq-distribution 4.7.0 ........................ SUCCESS [16:25 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 58:54 min
[INFO] Finished at: 2020-06-15T21:33:09+08:00
[INFO] ------------------------------------------------------------------------
看到以上信息,編譯安裝成功了
4.進入編譯成功後的目錄,啓動Name Server 和 Broker
cd /opt/module/rocketmq-all-4.7.0-source-release/distribution/target/rocketmq-4.7.0/rocketmq-4.7.0
#啓動Name Server
nohup sh bin/mqnamesrv &
#啓動Broker
nohup sh bin/mqbroker -n 192.168.126.70:9876 &
5.如果啓動broker提示如下錯誤需要手動調整虛擬機分配內存大小
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000005c0000000, 8589934592, 0) failed; error='Cannot allocate memory' (errno=12)
vim bin/runbroker.sh
更改67行內存大小(根據自己實際情況調整)
JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn2g"
6.看到如下信息代表成功啓動了
[root@localhost rocketmq-4.7.0]# jps
20289 Jps
10278 NamesrvStartup
20203 BrokerStartup
驗證服務正常運行
[root@localhost rocketmq-4.7.0]# export NAMESRV_ADDR=192.168.126.70:9876
[root@localhost rocketmq-4.7.0]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
SendResult [sendStatus=SEND_OK, msgId= ...
[root@localhost rocketmq-4.7.0]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
ConsumeMessageThread_%d Receive New Messages: [MessageExt...
7.服務關閉
[root@localhost rocketmq-4.7.0]# sh bin/mqshutdown broker
The mqbroker(20203) is running...
Send shutdown request to mqbroker(20203) OK
[root@localhost rocketmq-4.7.0]# sh bin/mqshutdown namesrv
The mqnamesrv(10278) is running...
Send shutdown request to mqnamesrv(10278) OK
以上就RocketMq 源碼安裝過程
Rocketmq圖形化界面安裝與使用
github地址:https://github.com/apache/rocketmq-externals
1.下載下來 進行Maven編譯,初次運行需要較長一段時間,打一盤王者的等待時間就夠了
cd /opt/module/rocketmq-externals/rocketmq-console
更新項目中的application.yml
設置Name Server連接地址
rocketmq.config.namesrvAddr=192.168.126.70:9876
#進行編譯
mvn clean package -Dmaven.test.skip=true
2.看到以下信息代表編譯安裝成功
[INFO]
[INFO] >>> maven-source-plugin:3.0.1:jar (attach-sources) > generate-sources @ rocketmq-console-ng >>>
[INFO]
[INFO] --- maven-checkstyle-plugin:2.17:check (validate) @ rocketmq-console-ng ---
[INFO] Starting audit...
Audit done.
[INFO]
[INFO] --- jacoco-maven-plugin:0.7.9:prepare-agent (default-prepare-agent) @ rocketmq-console-ng ---
[INFO] argLine set to -javaagent:/root/.m2/repository/org/jacoco/org.jacoco.agent/0.7.9/org.jacoco.agent-0.7.9-runtime.jar=destfile=/opt/module/rocketmq-externals/rocketmq-console/target/jacoco.exec
[INFO]
[INFO] <<< maven-source-plugin:3.0.1:jar (attach-sources) < generate-sources @ rocketmq-console-ng <<<
[INFO]
[INFO]
[INFO] --- maven-source-plugin:3.0.1:jar (attach-sources) @ rocketmq-console-ng ---
[INFO] Building jar: /opt/module/rocketmq-externals/rocketmq-console/target/rocketmq-console-ng-1.0.0-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25:22 min
[INFO] Finished at: 2020-06-15T22:31:28+08:00
[INFO] ------------------------------------------------------------------------
[root@localhost rocketmq-console]#
3.進入target包中執行 Java -jar rocketmq-console-ng-1.0.0.jar
訪問http://192.168.126.70:8080端口查看圖形化界面
4.圖形化界面上測試產生消息,shell進行消費
發送消息
消息產生成功
shell端進行消費
[root@localhost rocketmq-4.7.0]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
22:51:16.498 [main] DEBUG i.n.u.i.l.InternalLoggerFactory - Using SLF4J as the default logging framework
Consumer Started.
ConsumeMessageThread_1 Receive New Messages: [MessageExt [brokerName=localhost.localdomain, queueId=2, storeSize=188, queueOffset=250, sysFlag=0, bornTimestamp=1592232237604, bornHost=/192.168.126.70:47422, st
oreTimestamp=1592232237617, storeHost=/192.168.126.70:10911, msgId=C0A87E4600002A9F000000000002BEB2, commitLogOffset=179890, bodyCRC=691830935, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=251, KEYS=gcx, CONSUME_START_TIME=1592232676926, UNIQ_KEY=C0A87E465259681A95154CF9C6240000, WAIT=true, TAGS=tag}, body=[116, 111, 100, 97, 121, 32, 105, 115, 32, 97, 32, 104, 111, 116, 32, 100, 97, 121], transactionId='null'}]]
查看圖形界面已經被消費掉,延時隊列清空
首頁儀表盤查看剛剛新增的消息
Springboot與RocketMq的整合
1)創建springboot工程
2)添加pom.xml依賴
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.7.0</version>
</dependency>
3)jms簡易配置(只是爲了演示整合功能,實際中放到工程配置文件中)
package com.gcxzflgl.rocketmq.jms;
public class JmsConfig {
public static final String NAME_SERVER = "192.168.126.70:9876";
public static final String TOPIC = "autoCreateTopic";
}
生產者:
package com.gcxzflgl.rocketmq.jms;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.stereotype.Component;
@Component
public class PayProducer {
private String producerGroup = "pay_producer_group";
private DefaultMQProducer producer;
public PayProducer(){
producer = new DefaultMQProducer(producerGroup);
producer.setNamesrvAddr(JmsConfig.NAME_SERVER);
start();
}
public DefaultMQProducer getProducer(){
return this.producer;
}
/**
* 對象在使用之前必須要調用一次,只能初始化一次
*/
public void start(){
try {
this.producer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
}
/**
* 一般在應用上下文,使用上下文監聽器,進行關閉
*/
public void shutdown(){
this.producer.shutdown();
}
}
消費者:
package com.gcxzflgl.rocketmq.jms;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.util.List;
@Component
public class PayConsumer {
private DefaultMQPushConsumer consumer;
private String consumerGroup = "pay_consumer_group";
public PayConsumer() throws MQClientException {
consumer = new DefaultMQPushConsumer(consumerGroup);
consumer.setNamesrvAddr(JmsConfig.NAME_SERVER);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
consumer.subscribe(JmsConfig.TOPIC, "*");
//當有消息來臨時觸發監聽
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
try {
Message msg = msgs.get(0);
System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msgs.get(0).getBody()));
String topic = msg.getTopic();
String body = new String(msg.getBody(), "utf-8");
String tags = msg.getTags();
String keys = msg.getKeys();
System.out.println("topic=" + topic + ", tags=" + tags + ", keys=" + keys + ", msg=" + body);
//消息成功接收告訴Broker更新消息狀態
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
});
consumer.start();
System.out.println("consumer start ...");
}
}
rest訪問層
```java
package com.gcxzflgl.rocketmq.rest;
import com.gcxzflgl.rocketmq.jms.JmsConfig;
import com.gcxzflgl.rocketmq.jms.PayProducer;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
public class PayController {
@Autowired
private PayProducer payProducer;
@RequestMapping("/api/v1/pay_cb")
public Object callback(String text) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
Message message = new Message(JmsConfig.TOPIC,"taga", ("hello gcx rocketmq = "+text).getBytes() );
SendResult sendResult = payProducer.getProducer().send(message);
System.out.println(sendResult);
return "消息生產成功!";
}
}
4) 啓動項目 訪問地址: http://localhost:8080/api/v1/pay_cb?text=瑞燊兒
進行生產生產消息
idea控制檯打印:
SendResult [sendStatus=SEND_OK, msgId=AC24915B518418B4AAC251B3B31C0000, offsetMsgId=C0A87E4600002A9F000000000002C035, messageQueue=MessageQueue [topic=autoCreateTopic, brokerName=rocketmq-master, queueId=2], queueOffset=0]
ConsumeMessageThread_1 Receive New Messages: hello gcx rocketmq = 瑞燊兒
topic=autoCreateTopic, tags=taga, keys=null, msg=hello gcx rocketmq = 瑞燊兒
Rocketmq主從模式搭建
安裝步驟
1 . 前面已經講解過單機安裝過程,我們在以安裝Rocktmq的機器上進行克隆,克隆過程不再講解。確保兩臺機器上(192.168.126.70、192.168.126.71)上都安裝jdk1.8、maven 3.2+ 。
2 . 進入指定目錄複製一份作爲演示的主從節點配置(兩臺機器都要執行)
cd /opt/module/rocketmq-all-4.7.0-source-release/distribution/target/rocketmq-4.7.0/rocketmq-4.7.0/conf
cp -r 2m-2s-async/ m-s-async-disk
3 . 更改配置信息
master 節點:192.168.126.70
vim broker-a.proterties
namesrvAddr=192.168.126.70:9876;192.168.126.71:9876
brokerClusterName=GcxCluster
brokerName=broker-a #主節點和從節點名字需要相同
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER #主節點
flushDiskType=ASYNC_FLUSH #異步刷寫到磁盤
slave 節點:192.168.126.71
vim broker-a-s.properties
namesrvAddr=192.168.126.70:9876;192.168.126.71:9876
brokerClusterName=GcxCluster
brokerName=broker-a #主節點和從節點名字需要相同
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE #從節點
flushDiskType=ASYNC_FLUSH #異步刷寫到磁盤
4.啓動服務
主節點:
nohup sh bin/mqnamesrv &
nohup sh bin/mqbroker -c conf/m-s-async-disk/broker-a.properties &
從節點:
nohup sh bin/mqnamesrv &
nohup sh bin/mqbroker -c conf/m-s-async-disk/broker-a-s.properties &
5.使用可視化控制檯查看節點模式
至此,Rocketmq主從節點搭建完畢!
主從同步講解
- Broker分爲master和slave,一個master可以對應多個slave,反之不可以。master與slaver通過相同的Broker Name來匹配,不用的Broker id來定義是master還是slave。Broker向所有的NameServer節點建立長連接,定時註冊topic和發送元數據信息。NameServer定時(120s)掃描存活的Broker鏈接,超時沒響應斷開心跳檢測,對於consumer客戶端不能感知。consumer定時(30s)從NameServer獲取topic的信息,當Broker不可用時,consumer最多需要30s纔會發現
- 只有master能進行寫操作,slave不能進行寫入操作,同步策略取決於master
- 客戶端消費可以從master和slave消費,默認消費者都從master消費,如果master掛掉後,客戶端從NameServer感知Broker宕機,就會從slave進行消費,感知並非實時,slave不能保證master 100%的消息都同步過來了,會存在少量丟失,一旦master恢復,未同步過去的消息會被消費掉。
- 如果consumer實例的數量多於message queue的數量,多出來的consumer將無法分配到queue,無法起到負載均衡的作用,所以需要控制message queue的數量大於等於consumer的數量最好是成倍關係。
至此,RocketMq的使用講解完畢!