rocketmq的linux下C++版demo

寫在前面

    本文所記錄的是rocketmq的最最基本的操作項的demo,包含發送和接收數據,所寫的類也是比較簡單的實現,如要寫各種高大上的,請繞道,若對本文有異議的,可留言或發郵件給我~ths~~~
    寫消息隊列的都是大牛,我們不必非得自己又要看源碼,又要了解所有的細節,畢竟二牛也很難,生活如此簡單,很多事情就不要死磕了。
    這個demo是從rocketmq的demo中提煉出來的,有一些設置我也不知道爲啥要有,既然人家有,那麼我們就加上唄,也不會少一塊肉,需要詳細的深入的瞭解的時候再去了解咯~

    這個版本的位移(當前讀取到多少條了)是要自己手動控制的,遠程的我沒搞定,反正也不重要,就手動控制吧

簡易瞭解

    可以這麼理解:消息隊列是很高效的一條通道,我們創建一個主題(可理解爲通道),然後從通道的這邊發送,可以在另一邊接收到,不收語言等限制,如果另一邊沒有人接收,會暫時存儲起來,另一邊接收的時候可將前面的未接收的都接收到。

    rocketmq的c++版本,不需要自己創建主題,只需要調用發送和接收即可,當然,前面還有鏈接初始化這些。

準備工作

    要下載c++的源碼,目的是爲了得到rocketmq.a和include目錄
    鏈接:https://github.com/apache/rocketmq-externals/tree/master/rocketmq-cpp
    操作方法:1.下載該目錄;2.make命令編譯,得到rocketmq.a文件

    備註:過程中說缺啥就自己安裝吧~

代碼

main.cpp

#include <iostream>
#include <string>
#include "rocketmq.h"
using namespace std;
int main()
{
string strAdd = "192.1.2.123:9876";
long long llset = 26;
//consumer
CRocketMQ ConsumerOper(strAdd, llset);
//producer
CRocketMQ ProducerOper(strAdd);
//發送數據Key NOTIFY_DATA 0
string strTopic = "DATA";
string strTag = "TEST";
string strKey = "Key";
string strData = "123456789";
ProducerOper.vSendData(strTopic, strTag, strKey, strData);
//接收數據
list<string> lstrData;
while (true)
{
ConsumerOper.lgetData(strTopic, lstrData);
list<string>::iterator it = lstrData.begin();
for (; it != lstrData.end(); it++)
{
cout <<"[Info]" << *it << endl;
}
lstrData.clear();
}
return 0;
}

rocketmq.h

#ifndef __ROCKET_MQ_H__
#define __ROCKET_MQ_H__
/*
作者:wxy
郵箱:[email protected]
*/
#include <iostream>
#include <string>
#include <list>
#include "include/DefaultMQPullConsumer.h"
#include "include/DefaultMQProducer.h"
using namespace rmq;
using namespace std;
class CRocketMQ
{
public:
//consumer
CRocketMQ(string strAdd, long long llset);
//productor
CRocketMQ(string strAdd);
~CRocketMQ();
public:
//consumer接收消息,接收前需設置set(init)
long long lgetData(string strTopic, list<string>& lstrData);
//發送消息
void vSendData(string strTopic, string strTag, string strKey, string strData);
private:
//consumer初始化
void vInit(string strAdd, long long llset); 
//productor初始化
void vInit(string strAdd); 
private:
DefaultMQPullConsumer m_consumer;
DefaultMQProducer m_producer;
long long m_llOffSet;
bool m_bConsumerFlag;
bool m_bProducerFlag;
};
#endif

rocketmq.cpp

#include "rocketmq.h"

CRocketMQ::CRocketMQ(string strAdd, long long llset):m_consumer("DCS"),m_producer("DCS"),m_llOffSet(llset)
{
vInit(strAdd, llset);
m_bConsumerFlag = true;
m_bProducerFlag = false;
}
CRocketMQ::CRocketMQ(string strAdd):m_consumer("DCS"),m_producer("DCS")
{
vInit(strAdd);
m_bProducerFlag = true;
m_bConsumerFlag = false;
}
CRocketMQ::~CRocketMQ()
{
if (m_bConsumerFlag)
{
// 停止消費者
printf("[RocketMq]stop");
m_consumer.shutdown();
}
if (m_bProducerFlag)
{
// 停止生產者
printf("[RocketMq]stop");
m_producer.shutdown();
}
}
void CRocketMQ::vInit(string strAdd, long long llset) {
// 設置MQ的NameServer地址
printf("[RocketMq]Addr: %s\n", strAdd.c_str());
m_consumer.setNamesrvAddr(strAdd);
// 設置消費模式,CLUSTERING-集羣模式,BROADCASTING-廣播模式
printf("[RocketMq]Model: %s\n", getMessageModelString(CLUSTERING));
m_consumer.setMessageModel(CLUSTERING);
// 非阻塞模式,拉取超時時間,默認10s
m_consumer.setConsumerPullTimeoutMillis(4000);
// 長輪詢模式,Consumer連接在Broker掛起最長時間,默認20s
m_consumer.setBrokerSuspendMaxTimeMillis(3000);
// 長輪詢模式,拉取超時時間,默認30s
m_consumer.setConsumerTimeoutMillisWhenSuspend(5000);
// 啓動消費者
printf("[RocketMq]start\n");
m_consumer.start();
}
void CRocketMQ::vInit(string strAdd)
{
    // 設置MQ的NameServer地址
    printf("[RocketMq]Addr: %s\n", strAdd.c_str());
    m_producer.setNamesrvAddr(strAdd);
    // 啓動消費者
    printf("[RocketMq]start\n");
    m_producer.start();
}
//獲取消息,consumer消息
//返回值:當前set
long long CRocketMQ::lgetData(string strTopic, list<string>& lstrData)
{
while(true)
{
     // 獲取指定topic的路由信息
std::set<MessageQueue>* mqs = m_consumer.fetchSubscribeMessageQueues(strTopic);
std::set<MessageQueue>::iterator it = mqs->begin();
bool nFirst = true;
for (; it!=mqs->end(); it++)
{
MessageQueue mq = *it;
bool noNewMsg = false;
while (!noNewMsg)
{
try
{
// 拉取消息
//從指定set開始讀取
PullResult* pullResult = m_consumer.pull(mq, "*", m_llOffSet, 32);
if ((pullResult->pullStatus == FOUND) && (!pullResult->msgFoundList.empty()))
{
printf("[RocketMQ]獲取到消息 %d 條,當前位置 %lld ,整體位置 %lld\n", pullResult->msgFoundList.size(), pullResult->nextBeginOffset, m_llOffSet);
list<MessageExt*>::iterator it = pullResult->msgFoundList.begin();
for (;it!=pullResult->msgFoundList.end();it++)
{
string strData = string((*it)->getBody(), (*it)->getBodyLen());
lstrData.push_back(strData);
}
//以防萬一,此返回值存數大的
m_llOffSet = (pullResult->nextBeginOffset > m_llOffSet ? pullResult->nextBeginOffset : m_llOffSet);
//更新進度還用原來的
m_consumer.updateConsumeOffset(mq, pullResult->nextBeginOffset);
}
else
{
break;
}
delete pullResult;
}
catch (MQException& e)
{
std::cout<<e<<std::endl;
}
}
}
delete mqs;
if (!lstrData.empty())
{
return m_llOffSet;
}
}
return m_llOffSet;
}
//發送數據
void CRocketMQ::vSendData(string strTopic, string strTag, string strKey, string strData)
{
try
{
Message msg(strTopic, strTag, strKey, strData.c_str(), strData.size());
// 同步生產消息
m_producer.send(msg);
}
catch (MQClientException& e)
{
printf("[RocketMQ]數據發送失敗: [topic]%s[tag]%s[key]%s[info]%s[reason]%s\n", strTopic.c_str(), strTag.c_str(), strKey.c_str(), strData.c_str(), e.what());
}
}

make.sh

g++ -g -o a.out *.cpp -lrocketmq -I./include -lz -lrt -lpthread

-------------------------------------------

2018年8月2日更新:

rocketmq.a這個文件,如果沒export查找lib的路徑,建議放在/user/locale/lib目錄,如果需要放在當前目錄下執行,需要執行之前設置lib的查找路徑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章