1.RocketMQ安裝
-
首先需要安裝maven工具,因爲RocketMq是使用java代碼實現的,官方的工程使用maven構建,所以需要現在本地安裝maven工具
-
下載 RocketMq 壓縮包,將壓縮文件解壓到想要安裝的目錄
#我的是MAC環境,所以這裏以mac環境爲例 #解壓並進入安裝目錄 cd /Users/kangning/apache/rocketmq/ unzip rocketmq-all-4.4.0-source-release.zip
-
使用maven編譯下載的源文件
#進入文件目錄 cd rocketmq-all-4.4.0/ #對源文件進行編譯 mvn -Prelease-all -DskipTests clean install -U
-
啓動Name Server
#進入變異完的目錄 cd distribution/target/apache-rocketmq #啓動Name Server nohup sh bin/mqnamesrv & #查看是否啓動 成功 tail -f ~/logs/rocketmqlogs/namesrv.log #出現:**The Name Server boot success...** 說明成功
-
啓動Broker
#啓動Broker nohup sh bin/mqbroker -n localhost:9876 & #查看是否啓動成功 tail -f ~/logs/rocketmqlogs/broker.log #出現 **The broker[%s, 172.30.30.233:10911] boot success...** 說明啓動成功
-
關閉服務
#關閉broker sh bin/mqshutdown broker #出現如下則成功:**The mqbroker(36695) is running... Send shutdown request to mqbroker(36695) OK** #關閉nameserver sh bin/mqshutdown namesrv #出現如下則成功:**The mqnamesrv(36664) is running... Send shutdown request to mqnamesrv(36664) OK**
2.RocketMQ客戶端
- 進入rocketmq-externals項目GitHub地址,選擇對應的rocketmq-console分支,如下圖,可以看到對應的代碼,將代碼clone到本地。因爲只需要分支的代碼,所以下載對應的分支就可以
$ git clone -b release-rocketmq-console-1.0.0 https://github.com/apache/rocketmq-externals.git
-
進入項目文件夾並修改配置文件
cd rocketmq-externals/rocketmq-console/ vi src/main/resources/application.properties
配置文件內容:
#管理後臺訪問上下文路徑,默認爲空,如果填寫,一定要前面加“/”,後面不要加,否則啓動報錯 server.contextPath=/rocketmq #訪問端口 server.port=8080 #spring.application.index=true spring.application.name=rocketmq-console spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true #logback配置文件路徑 logging.config=classpath:logback.xml #if this value is empty,use env value rocketmq.config.namesrvAddr NAMESRV_ADDR | now, you can set it in ops page.default localhost:9876 #Name Server地址,修改成你自己的服務地址 rocketmq.config.namesrvAddr=10.0.74.198:9876;10.0.74.199:9876 #if you use rocketmq version < 3.5.8, rocketmq.config.isVIPChannel should be false.default true rocketmq.config.isVIPChannel= #rocketmq-console's data path:dashboard/monitor rocketmq.config.dataPath=/tmp/rocketmq-console/data #set it false if you don't want use dashboard.default true rocketmq.config.enableDashBoardCollect=true
-
編譯jar包並啓動客戶端命令
mvn clean package -Dmaven.test.skip=true java -jar target/rocketmq-console-ng-1.0.0.jar
-
訪問路徑本地路徑:http://localhost:8080/rocketmq 即可在頁面操作
3.發送/接收消息
首先需要在客戶端創建消息隊列:TestQueue
1. 生產者代碼實現
- 創建生產者代理對象
/** * @author kangning Date: 2019-04-22 Time: 15:50 * @version $Id$ */ public class CommonDemoProderProxy { private static final Logger logger = LoggerFactory.getLogger(CommonDemoProderProxy.class); private DefaultMQProducer defaultMQProducer; private String nameSrv; private String groupName; private String instanceName; private int retryTimes; public CommonDemoProderProxy(String nameSrv, String groupName, String instanceName, int retryTimes) { try { this.nameSrv = nameSrv; this.groupName = groupName; this.instanceName = instanceName; this.retryTimes = retryTimes; //新建生產者對象 this.defaultMQProducer = new DefaultMQProducer(groupName); //設置nameserver this.defaultMQProducer.setNamesrvAddr(nameSrv); //設置實例名稱 this.defaultMQProducer.setInstanceName(instanceName); //設置失敗重試次數 this.defaultMQProducer.setRetryTimesWhenSendFailed(retryTimes); //啓動實例 this.defaultMQProducer.start(); } catch (MQClientException e) { logger.error("init rocket produce error", e); } } /** * 實際調用生產者發送消息的接口 * @param message * @return * @throws InterruptedException * @throws RemotingException * @throws MQClientException * @throws MQBrokerException */ public SendResult sendMsg(Message message) throws InterruptedException, RemotingException, MQClientException, MQBrokerException { return defaultMQProducer.send(message); } public DefaultMQProducer getDefaultMQProducer() { return defaultMQProducer; } public void setDefaultMQProducer(DefaultMQProducer defaultMQProducer) { this.defaultMQProducer = defaultMQProducer; } public String getNameSrv() { return nameSrv; } public void setNameSrv(String nameSrv) { this.nameSrv = nameSrv; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public String getInstanceName() { return instanceName; } public void setInstanceName(String instanceName) { this.instanceName = instanceName; } public int getRetryTimes() { return retryTimes; } public void setRetryTimes(int retryTimes) { this.retryTimes = retryTimes; } @Override public String toString() { return "CommonDemoProderProxy{" + "defaultMQProducer=" + defaultMQProducer + ", nameSrv='" + nameSrv + '\'' + ", groupName='" + groupName + '\'' + '}'; } }
- 配置生產者代理信息
<bean id="commonDemoProderProxy" class="com.kangning.demo.framework.mq.CommonDemoProderProxy"> <constructor-arg name="groupName" value="${rocketmq.group}"/> <constructor-arg name="nameSrv" value="${rocketmq.namespace}"/> <constructor-arg name="instanceName" value="${rocketmq.instanceName}"/> <constructor-arg name="retryTimes" value="${rocketmq.retryTimes}"/> </bean>
- 添加基礎生產者抽象類
/** * @author kangning Date: 2019-04-22 Time: 16:39 * @version $Id$ */ public abstract class BaseCommonProducer<T> { private static final Logger logger = LoggerFactory.getLogger(BaseCommonProducer.class); @Autowired private CommonDemoProderProxy commonDemoProderProxy; private String topicName; public SendResult sendMsg(T object){ Message message = new Message(this.getTopicName(), JSONObject.toJSONString(object).getBytes()); try { return commonDemoProderProxy.sendMsg(message); } catch (InterruptedException | RemotingException | MQClientException | MQBrokerException e) { logger.error("send rocketMq msg error", e); e.printStackTrace(); } return null; } public String getTopicName() { return topicName; } public void setTopicName(String topicName) { this.topicName = topicName; } }
- 添加具體生產者實現類
/** * @author kangning Date: 2019-04-22 Time: 16:57 * @version $Id$ */ public class TestProducer extends BaseCommonProducer<RegionInfo> { }
- 配置具體生產者信息
<bean id="testProducer" class="com.kangning.demo.rocketmq.producer.TestProducer"> <property name="topicName" value="TestQueue"/> </bean>
2. 消費者代碼實現
- 創建消費者公共抽象類(用於規範共有的業務邏輯以及接收到消息之後回調接口處理消息)
/** * @author kangning Date: 2019-04-22 Time: 16:39 * @version $Id$ */ public abstract class BaseCommonConsumer<T> { private static final Logger logger = LoggerFactory.getLogger(BaseCommonConsumer.class); public abstract boolean receive(MessageExt messageExt); }
- 添加具體的消費者實現
/** * @author kangning Date: 2019-04-22 Time: 17:09 * @version $Id$ */ public class TestConsumer extends BaseCommonConsumer<RegionInfo> { @Override public boolean receive(MessageExt messageExt) { String msgStr = new String(messageExt.getBody()); RegionInfo regionInfo = JSONObject.parseObject(msgStr,RegionInfo.class); System.out.println(regionInfo.getRegionCN()); return true; } }
- 配置消費者bean
<bean id="testConsumer" class="com.kangning.demo.rocketmq.consumer.TestConsumer"/>
- 添加消費者代理類
/** * @author kangning Date: 2019-04-22 Time: 17:17 * @version $Id$ */ public class CommonDemoConsumerProxy { private static final Logger logger = LoggerFactory.getLogger(CommonDemoConsumerProxy.class); private final Map<String, BaseCommonConsumer> topics; private String nameSrv; private String groupName; private DefaultMQPushConsumer defaultMQPushConsumer; private String messageModel; private int reconsumeTimes; public CommonDemoConsumerProxy(Map<String, BaseCommonConsumer> topics, String nameSrv, String groupName, String messageModel, int reconsumeTimes) { //檢查消息隊列配置 if (CollectionUtils.isEmpty(topics)){ logger.error("no topic={} for group", groupName); topics = new HashMap<>(0); } this.topics = topics; this.nameSrv = nameSrv; this.groupName = groupName; this.defaultMQPushConsumer = new DefaultMQPushConsumer(); this.messageModel = messageModel; this.reconsumeTimes = reconsumeTimes; MessageModel enumMessageModel = null; if (StringUtils.isNoneBlank(this.messageModel)){ enumMessageModel = EnumUtils.getEnum(MessageModel.class, this.messageModel); } //初始化消費者信息 initConsumer(topics, nameSrv, groupName, enumMessageModel, reconsumeTimes); } private void initConsumer(Map<String, BaseCommonConsumer> topics,String nameSrv, String groupName, MessageModel messageModel, int reconsumeTimes) { try { //設置nameserver this.defaultMQPushConsumer.setNamesrvAddr(nameSrv); //設置消費者組 this.defaultMQPushConsumer.setConsumerGroup(groupName); //設置啓動時消費起始點 this.defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); //設置消費失敗重試次數 this.defaultMQPushConsumer.setMaxReconsumeTimes(reconsumeTimes); //設置消費模式 if (messageModel == null){ //默認集羣模式 this.defaultMQPushConsumer.setMessageModel(MessageModel.CLUSTERING); }else { this.defaultMQPushConsumer.setMessageModel(messageModel); } //訂閱消費隊列 for (Entry<String, BaseCommonConsumer> entry : topics.entrySet()){ this.defaultMQPushConsumer.subscribe(entry.getKey(), "*"); } //註冊回調接口 this.defaultMQPushConsumer.registerMessageListener(new MessageListenerConcurrently() { //消費消息 @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { for (MessageExt messageExt : msgs){ //獲取消息隊列對應的具體消費者 BaseCommonConsumer baseCommonConsumer = topics.get(messageExt.getTopic()); if (baseCommonConsumer == null){ logger.error("no topic={} for service", messageExt.getTopic()); } try { //調用回調接口receive處理消息 if (baseCommonConsumer== null || !baseCommonConsumer.receive(messageExt)){ //返回消費失敗 return ConsumeConcurrentlyStatus.RECONSUME_LATER; } } catch (Exception var6) { logger.error("consumer message error", var6); return ConsumeConcurrentlyStatus.RECONSUME_LATER; } } //返回消費成功 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); //啓動消費者實例 this.defaultMQPushConsumer.start(); } catch (MQClientException e) { logger.error("init rocket consumer error", e); } } public Map<String, BaseCommonConsumer> getTopics() { return topics; } public String getNameSrv() { return nameSrv; } public void setNameSrv(String nameSrv) { this.nameSrv = nameSrv; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public DefaultMQPushConsumer getDefaultMQPushConsumer() { return defaultMQPushConsumer; } public void setDefaultMQPushConsumer(DefaultMQPushConsumer defaultMQPushConsumer) { this.defaultMQPushConsumer = defaultMQPushConsumer; } public String getMessageModel() { return messageModel; } public void setMessageModel(String messageModel) { this.messageModel = messageModel; } public int getReconsumeTimes() { return reconsumeTimes; } public void setReconsumeTimes(int reconsumeTimes) { this.reconsumeTimes = reconsumeTimes; } @Override public String toString() { return "CommonDemoConsumerProxy{" + "topics=" + topics + ", nameSrv='" + nameSrv + '\'' + ", groupName='" + groupName + '\'' + ", defaultMQPushConsumer=" + defaultMQPushConsumer + ", messageModel='" + messageModel + '\'' + ", reconsumeTimes=" + reconsumeTimes + '}'; } }
- 配置消費者代理對象信息
<bean id="commonDemoConsumerProxy" class="com.kangning.demo.framework.mq.CommonDemoConsumerProxy"> <constructor-arg name="groupName" value="TestGroup"/> <constructor-arg name="nameSrv" value="${rocketmq.namespace}"/> <constructor-arg name="topics"> <map> <entry key="TestQueue" value-ref="testConsumer"/> </map> </constructor-arg> <!--配置參照: org.apache.rocketmq.common.protocol.heartbeat.MessageModel--> <constructor-arg name="messageModel" value="CLUSTERING"/> <constructor-arg name="reconsumeTimes" value="3"/> </bean>
到這裏一個簡單的RocketMQ就基本實現了,啓動項目,發送消息即可收到信息