基於 ZEROMQ 封裝的通信模塊--SEED_CZMQ

SEED_CZMQ----基於 ZEROMQ 封裝的通信模塊

  1. Zeromq 簡介:

ZeroMQ號稱是“史上最快的消息隊列”,基於c語言開發的,實時流處理sorm的task之間的通信就是用的zeroMQ。
ZeroMQ可以簡化網絡開發。該通信模塊用於微服務內部通信十分簡單,高效。是理想的微服務內部的RPC通信工具

  1. 代碼結構:
     SEED_CZMQ--|
                |
                |---include----|
                |              |---seed_bp_czmq_api.h----->對外接口頭文件,用於調用
                |              |
                | 
                |---src--------|
                |              |----seed_czmq_client.h----->客戶端模塊內部實現的頭文件
                |              |----seed_czmq_server.h----->服務端模塊內部實現的頭文件
                |              |----seed_czmq_client.cpp----->服務端模塊內部實現的源代碼
                |              |----seed_czmq_server.cpp---服務端模塊內部實現的源代碼
                |              |----seed_bp_czmq_api.cpp---對外接口的具體實現
                |
                |
                |
                |----mk--------|
                |              |-----CMakefile----->編譯文件(支持windows linux 跨平臺編譯)
                |
                |---exlib------|----linux--->boost linux庫
                |              |----windows--->boost windows庫
                |              |----windows--->boost windows庫
                |             
                |--------->README--工程說明文件    

3.SEED_CZMQ庫說明:

SEED_CZMQ 是基於ZEROMQ開發的RPC通信模塊。用於微服務之間通信。是SEED_CLOUD微服務框架的重要模塊。

4.代碼說明:

/*
@filename: seed_bp_czmq_api.h
@comment: zeromq interface
*/
#ifndef SEED_BP_SEED_BP_CZMQ_API_H
#define SEED_BP_SEED_BP_CZMQ_API_H
#include <map>
#include <string>
#include <cstdarg>
#include <seed_engine_def.hpp>
enum CmqType{
    CZMQ_PAIR=0,
    CZMQ_REQ,
    CZMQ_REP,
    CZMQ_PUB,
    CZMQ_SUB,
    CZMQ_DELAR,
    CZMQ_ROUTER,
    TYEP_INVALID
};

enum CmqStats{
    CZMQ_START=0,
    CZMQ_STOP=1,
    CZMQ_INVALID
};

struct SEED_API SeedNode
{
    typedef SD_ULONG32 (*message_call_back)(void* msg);
    std::string m_net_path;
    void* m_inserver = nullptr;
    void* m_inclient = nullptr;
    void* m_net = nullptr;
    void* m_scontrol = nullptr;
    void* m_icontrol = nullptr;
    SD_ULONG32 m_uid=0;
    SD_ULONG32 m_stats=CZMQ_STOP;
    SD_ULONG32 m_type=0;
    SD_LONG32  m_timeout=-1;
    std::string m_id;
    message_call_back m_callback = nullptr;
};

class SEED_API SeedCZMQLog{

public:

    static void set_log_callback(log_callback logfunc, SD_ULONG32 logID) {
        s_logfunc = logfunc;
        s_logID = logID;
        return;
    }

    static void log(IN SD_ULONG32 level, const char* filename, SD_ULONG32 lineid, const char* fmt, ...) {
        va_list vArgList;
        va_start(vArgList, fmt);
        if (SeedCZMQLog::s_logfunc)
        {
            SeedCZMQLog::s_logfunc(s_logID, level, filename, lineid, fmt, vArgList);
        }
        va_end(vArgList);
        return;
    }

private:
    static log_callback s_logfunc ;
    static unsigned int s_logID ;
};

class SEED_API SeedZmqBase{
public:
    virtual  SD_ULONG32 ZmqStart()   = 0;
    virtual  SD_ULONG32 ZmqStop()    = 0;
    virtual  SD_ULONG32 ZmqSend()    = 0;
    virtual  SD_ULONG32 ZmqReset()   = 0;
    virtual  SD_ULONG32 CreatePool() = 0;
    virtual  SD_ULONG32 ZmqSetBeOpt()  = 0;
    virtual  SD_ULONG32 ZmqSetAfOpt()  = 0;
    virtual  SD_ULONG32 ZmqInit(std::string adress,SD_ULONG32 ultype) = 0;
};

class SEED_API SeedCzmqFactory{
public:
    SD_ULONG32 CreateServer(IN std::string adress,IN SD_ULONG32 ultype, OUT SD_ULONG32 & id);
    SD_ULONG32 CreateClient(IN std::string adress,IN SD_ULONG32 ultype, OUT SD_ULONG32 & id);
private:
    SD_ULONG32 m_sadapter = 0;
    SD_ULONG32 m_cadapter = 0;
    std::map<SD_ULONG32,SeedZmqBase*> m_servers;
    std::map<SD_ULONG32,SeedZmqBase*> m_clients;
};
#endif //SEED_BP_SEED_BP_CZMQ_API_H

/*
@filename: seed_bp_czmq_api.cpp
@comment: zeromq interface
*/

#include <seed_bp_czmq_api.h>

SD_ULONG32 SeedCzmqFactory::CreateServer(std::string adress, SD_ULONG32 ultype, SD_ULONG32 &id) {
    return 0;
}

SD_ULONG32 SeedCzmqFactory::CreateClient(std::string adress, SD_ULONG32 ultype, SD_ULONG32 &id) {
    return 0;
}
/*
@filename: seed_czmq_client.h
@comment:
log example
*/

#ifndef SEED_BP_SEED_CZMQ_CLIENT_H
#define SEED_BP_SEED_CZMQ_CLIENT_H

#include <czmq.h>
#include <seed_bp_czmq_api.h>

class SeedCzmqClient : public SeedZmqBase {

    unsigned int ZmqStart() override;

    unsigned int ZmqStop() override;

    unsigned int ZmqSend() override;

    unsigned int CreatePool() override;

    unsigned int ZmqReset() override;

    unsigned int ZmqInit(std::string adress, SD_ULONG32 ultype) override;

    unsigned int ZmqSetBeOpt() override;

    unsigned int ZmqSetAfOpt() override;
private:
    SeedNode m_node;
};

#define SEED_ZMQC_LOG0(level,message) if(1){ SeedCZMQLog::log(level,__FILE__,__LINE__,message);}


#define SEED_ZMQC_LOG1(level,fmt,v1) if(1){SeedCZMQLog::log(level,__FILE__,__LINE__,fmt,v1);}


#define SEED_ZMQC_LOG2(level,message,v1,v2) if(1){SeedCZMQLog::log(level,__FILE__,__LINE__,message,v1,v2);}

#endif //SEED_BP_SEED_CZMQ_CLIENT_H

/*
@filename: seed_czmq_client.cpp
@comment:
log example
*/

#include "seed_czmq_client.h"

unsigned int SeedCzmqClient::ZmqStart() {
    return this->CreatePool();
}

unsigned int SeedCzmqClient::ZmqStop() {
    SD_ULONG32 ulret =ERROR_BASE_SUCCEED;
    if (m_node.m_stats == CZMQ_STOP){
        SEED_ZMQC_LOG1(SD_LOG_INFO,"CZMQ alread stop [%s]", m_node.m_net_path.c_str());
        return ulret;
    }
    zmsg_t * msg = zmsg_new();
    if(msg != nullptr){
        zmsg_pushstr(msg,"SEED_QUIT");
        SD_LONG32 ret = zmsg_send(&msg,m_node.m_icontrol);
        if(ret != -1){
			return ERROR_BASE_FALT;
        }
        zmsg_destroy(&msg);
    }
    return ulret;
}

unsigned int SeedCzmqClient::ZmqSend() {
    return 0;
}

unsigned int SeedCzmqClient::ZmqReset() {
    this->ZmqStop();
    BP_Sleep(3);
    this->ZmqStart();
    return 0;}

unsigned int SeedCzmqClient::CreatePool() {
	SD_ULONG32 ulret = ERROR_BASE_SUCCEED;
    if(m_node.m_inclient == nullptr ||
       m_node.m_net == nullptr ||
       m_node.m_inserver == nullptr ||
       m_node.m_icontrol == nullptr ||
       m_node.m_scontrol == nullptr)
    {
		SEED_ZMQC_LOG0(SD_LOG_INFO, "Fail create ZMQ Poll...");
		return ERROR_BASE_FALT;
    }
    while (true){

        zmq_pollitem_t items[] = {
                {zsock_resolve(m_node.m_inserver),0,ZMQ_POLLIN,0},
                {zsock_resolve(m_node.m_scontrol),0,ZMQ_POLLIN,0},
                {zsock_resolve(m_node.m_net),0,ZMQ_POLLIN,0}
        };
        m_node.m_type = CZMQ_START;
        zmq_poll(items,2,m_node.m_timeout);
        if (items[0].revents & ZMQ_POLLIN){
            zmsg_t * data = zmsg_recv(m_node.m_inserver);
            if (data == nullptr){
                break;
            }
            zmsg_send(&data,m_node.m_net);
            zmsg_destroy(&data);
            data = nullptr;
        }
        if (items[1].revents & ZMQ_POLLIN){
            zmsg_t * data = zmsg_recv(m_node.m_scontrol);
            if (data == nullptr){
                break;
            }
            if(zmsg_size(data) != 1){
                zmsg_destroy(&data);
                break;
            }
            zframe_t * frame = zmsg_next(data);
            if (std::string("SEED_QUIT") == std::string((char*)zframe_data(frame),zframe_size(frame))){
                zmsg_destroy(&data);
                data = nullptr;
                break;
            }
            zmsg_destroy(&data);
            data = nullptr;
        }
        if (items[2].revents & ZMQ_POLLIN) {
            zmsg_t * data = zmsg_recv(m_node.m_net);
            if (data == nullptr){
                break;
            }
            if (m_node.m_callback){
                m_node.m_callback(static_cast<void*>(data));
            }
            if (data != nullptr){
                zmsg_destroy(&data);
            }
        }
        else{
			SEED_ZMQC_LOG1(SD_LOG_INFO, "EPOLL MESSAGE TIMEOUT [%d]'S...", m_node.m_timeout);
            if (m_node.m_stats == CZMQ_STOP){
				SEED_ZMQC_LOG0(SD_LOG_INFO, "check CMQ is STOP so break epoll");
                break;
            }
        }
    }
    m_node.m_type = CZMQ_STOP;
    if (m_node.m_inserver){
        zsock_destroy((zsock_t**)(&m_node.m_inserver));
        m_node.m_inserver= nullptr;
    }
    if (m_node.m_inclient){
        zsock_destroy((zsock_t**)(&m_node.m_inclient));
        m_node.m_inclient= nullptr;
    }
    if (m_node.m_icontrol){
        zsock_destroy((zsock_t**)(&m_node.m_icontrol));
        m_node.m_icontrol= nullptr;
    }
    if (m_node.m_scontrol){
        zsock_destroy((zsock_t**)(&m_node.m_scontrol));
        m_node.m_scontrol= nullptr;
    }
    if (m_node.m_net){
        zsock_destroy((zsock_t**)(&m_node.m_net));
        m_node.m_net= nullptr;
    }
    return ERROR_BASE_SUCCEED;
}

unsigned int SeedCzmqClient::ZmqInit(std::string adress, SD_ULONG32 ultype) {
	SD_ULONG32 ulret = ERROR_BASE_SUCCEED;
    try
    {
        m_node.m_inserver = zsock_new(ZMQ_PAIR);
        m_node.m_inclient = zsock_new(ZMQ_PAIR);
        m_node.m_icontrol = zsock_new(ZMQ_PAIR);
        m_node.m_scontrol = zsock_new(ZMQ_PAIR);
        m_node.m_net = zsock_new(ultype);
        m_node.m_stats = CZMQ_STOP;
        this->ZmqSetBeOpt();
        int ret = zsock_bind(static_cast<zsock_t*>(m_node.m_inserver),"inproc://czmq_client_inter_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQC_LOG1(SD_LOG_ERROR, "fail connect inproc://czmq_client_inter_%d", m_node.m_uid);
            this->ZmqStop();
			return  ERROR_BASE_FALT;
        }
        ret = zsock_connect(static_cast<zsock_t*>(m_node.m_inclient),"inproc://czmq_client_inter_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQC_LOG1(SD_LOG_ERROR, "fail connect inproc://czmq_client_inter_%d", m_node.m_uid);
            this->ZmqStop();
			return  ERROR_BASE_FALT;
        }
        ret = zsock_bind(static_cast<zsock_t*>(m_node.m_inserver),"inproc://czmq_client_control_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQC_LOG1(SD_LOG_ERROR, "fail bind inproc://czmq_client_control_%d", m_node.m_uid);
            this->ZmqStop();
			return  ERROR_BASE_FALT;
        }
        ret = zsock_connect(static_cast<zsock_t*>(m_node.m_inclient),"inproc://czmq_client_control_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQC_LOG1(SD_LOG_ERROR, "fail connect inproc://czmq_client_control_%d", m_node.m_uid);
            this->ZmqStop();
			return ERROR_BASE_FALT;
        }
        ret = zsock_connect(static_cast<zsock_t*>(m_node.m_net),adress.c_str());
		if (ret != ERROR_BASE_SUCCEED) {
            SEED_ZMQC_LOG1(SD_LOG_ERROR,"fail bind path %s", adress.c_str());
            this->ZmqStop();
			return ERROR_BASE_FALT;
        }
        this->ZmqSetAfOpt();
    }
    catch (std::exception& e)
    {
		SEED_ZMQC_LOG1(SD_LOG_ERROR, "fail create client exception [%s]", e.what());
        this->ZmqStop();
    }
    return ulret;
}

unsigned int SeedCzmqClient::ZmqSetBeOpt() {
    return 0;
}

unsigned int SeedCzmqClient::ZmqSetAfOpt() {
    return 0;
}
//
// Created by yang shaofei on 2019-05-31.
/*
@filename: seed_czmq_server.h
@comment:
log example
*/
#ifndef SEED_BP_SEED_CZMQ_SERVER_H
#define SEED_BP_SEED_CZMQ_SERVER_H

#include <czmq.h>
#include <seed_bp_czmq_api.h>

class SeedCzmqServer :public SeedZmqBase {
public:
private:
    virtual unsigned int ZmqStart() override;

    virtual unsigned int ZmqSend() override;

    virtual unsigned int ZmqStop() override;

    unsigned int ZmqReset() override;

    unsigned int CreatePool() override;

    unsigned int ZmqInit(std::string adress, SD_ULONG32 ultype) override;

    unsigned int ZmqSetBeOpt() override;

    unsigned int ZmqSetAfOpt() override;

private:
    SeedNode m_node;
};
#define SEED_ZMQS_LOG0(level,message) if(1){ SeedCZMQLog::log(level,__FILE__,__LINE__,message);}


#define SEED_ZMQS_LOG1(level,fmt,v1) if(1){SeedCZMQLog::log(level,__FILE__,__LINE__,fmt,v1);}


#define SEED_ZMQS_LOG2(level,message,v1,v2) if(1){SeedCZMQLog::log(level,__FILE__,__LINE__,message,v1,v2);}

#endif //SEED_BP_SEED_CZMQ_SERVER_H

/*
@filename: seed_czmq_server.cpp
@comment:
log example
*/
#include <czmq.h>
#include <exception>
#include "seed_czmq_server.h"

unsigned int SeedCzmqServer::ZmqInit(std::string adress, SD_ULONG32 ultype) {
    SD_ULONG32 ulret = ERROR_BASE_SUCCEED;
    try
    {
        m_node.m_inserver = zsock_new(ZMQ_PAIR);
        m_node.m_inclient = zsock_new(ZMQ_PAIR);
        m_node.m_icontrol = zsock_new(ZMQ_PAIR);
        m_node.m_scontrol = zsock_new(ZMQ_PAIR);
        m_node.m_net = zsock_new(ultype);
        m_node.m_stats = CZMQ_STOP;
        this->ZmqSetBeOpt();
        int ret = zsock_bind(static_cast<zsock_t*>(m_node.m_inserver),"inproc://czmq_server_inter_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQS_LOG1(SD_LOG_ERROR, "fail connect inproc://czmq_server_inter_%d", m_node.m_uid);
            this->ZmqStop();
			return  ERROR_BASE_FALT;
        }
        ret = zsock_connect(static_cast<zsock_t*>(m_node.m_inclient),"inproc://czmq_server_inter_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQS_LOG1(SD_LOG_ERROR, "fail connect inproc://czmq_server_inter_%d", m_node.m_uid);
            this->ZmqStop();
			return  ERROR_BASE_FALT;
        }
        ret = zsock_bind(static_cast<zsock_t*>(m_node.m_inserver),"inproc://czmq_server_control_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQS_LOG1(SD_LOG_ERROR, "fail bind inproc://czmq_server_control_%d", m_node.m_uid);
            this->ZmqStop();
			return  ERROR_BASE_FALT;
        }
        ret = zsock_connect(static_cast<zsock_t*>(m_node.m_inclient),"inproc://czmq_server_control_%d",m_node.m_uid);
		if (ret != ERROR_BASE_SUCCEED){
			SEED_ZMQS_LOG1(SD_LOG_ERROR, "fail connect inproc://czmq_server_control_%d", m_node.m_uid);
            this->ZmqStop();
			return ERROR_BASE_FALT;
        }
        ret = zsock_bind(static_cast<zsock_t*>(m_node.m_net),adress.c_str());
		if (ret != ERROR_BASE_SUCCEED) {
			SEED_ZMQS_LOG1(SD_LOG_ERROR, "fail bind path %s", adress.c_str());
            this->ZmqStop();
			return ERROR_BASE_FALT;
        }
        this->ZmqSetAfOpt();
    }
    catch (std::exception& e)
    {
		SEED_ZMQS_LOG1(SD_LOG_ERROR, "fail create server exception [%s]", e.what());
        this->ZmqStop();
    }
    return ulret;
}

unsigned int SeedCzmqServer::ZmqStart() {
    return  this->CreatePool();
}

unsigned int SeedCzmqServer::ZmqStop() {
	SD_ULONG32 ulret = ERROR_BASE_SUCCEED;
    if (m_node.m_stats == CZMQ_STOP){
        SEED_ZMQS_LOG1(SD_LOG_INFO,"CZMQ alread stop [%s]", m_node.m_net_path.c_str());
        return ulret;
    }
    zmsg_t * msg = zmsg_new();
    if(msg != nullptr){
        zmsg_pushstr(msg,"SEED_QUIT");
        SD_LONG32 ret = zmsg_send(&msg,m_node.m_icontrol);
        if(ret != -1){
			return ERROR_BASE_FALT;
        }
        zmsg_destroy(&msg);
    }
    return ulret;
}

unsigned int SeedCzmqServer::ZmqSend() {
    return 0;
}

unsigned int SeedCzmqServer::ZmqReset() {
    this->ZmqStop();
    BP_Sleep(3);
    this->ZmqStart();
    return 0;
}

unsigned int SeedCzmqServer::CreatePool() {

	SD_ULONG32 ulret = ERROR_BASE_SUCCEED;
    if(m_node.m_inclient == nullptr ||
       m_node.m_net == nullptr ||
       m_node.m_inserver == nullptr ||
       m_node.m_icontrol == nullptr ||
       m_node.m_scontrol == nullptr)
    {
		SEED_ZMQS_LOG0(SD_LOG_INFO, "Fail create ZMQ Poll...");
        return ERROR_BASE_FALT;
    }
    while (true){

        zmq_pollitem_t items[] = {
                {zsock_resolve(m_node.m_inserver),0,ZMQ_POLLIN,0},
                {zsock_resolve(m_node.m_scontrol),0,ZMQ_POLLIN,0},
                {zsock_resolve(m_node.m_net),0,ZMQ_POLLIN,0}
        };
        m_node.m_type = CZMQ_START;
        zmq_poll(items,2,m_node.m_timeout);
        if (items[0].revents & ZMQ_POLLIN){
            zmsg_t * data = zmsg_recv(m_node.m_inserver);
            if (data == nullptr){
                break;
            }
            zmsg_send(&data,m_node.m_net);
            zmsg_destroy(&data);
            data = nullptr;
        }
        if (items[1].revents & ZMQ_POLLIN){
            zmsg_t * data = zmsg_recv(m_node.m_scontrol);
            if (data == nullptr){
                break;
            }
            if(zmsg_size(data) != 1){
                zmsg_destroy(&data);
                break;
            }
            zframe_t * frame = zmsg_next(data);
            if (std::string("SEED_QUIT") == std::string((char*)zframe_data(frame),zframe_size(frame))){
                zmsg_destroy(&data);
                data = nullptr;
                break;
            }
            zmsg_destroy(&data);
            data = nullptr;
        }
        if (items[2].revents & ZMQ_POLLIN) {
            zmsg_t * data = zmsg_recv(m_node.m_net);
            if (data == nullptr){
                break;
            }
            if (m_node.m_callback){
                m_node.m_callback(static_cast<void*>(data));
            }
            if (data != nullptr){
                zmsg_destroy(&data);
            }
        }
        else{
			SEED_ZMQS_LOG1(SD_LOG_INFO, "EPOLL MESSAGE TIMEOUT [%d]'S...", m_node.m_timeout);
            if (m_node.m_stats == CZMQ_STOP){
				SEED_ZMQS_LOG0(SD_LOG_INFO, "check CMQ is STOP so break epoll");
                break;
            }
        }
    }
    m_node.m_type = CZMQ_STOP;
    if (m_node.m_inserver){
        zsock_destroy((zsock_t**)(&m_node.m_inserver));
        m_node.m_inserver= nullptr;
    }
    if (m_node.m_inclient){
        zsock_destroy((zsock_t**)(&m_node.m_inclient));
        m_node.m_inclient= nullptr;
    }
    if (m_node.m_icontrol){
        zsock_destroy((zsock_t**)(&m_node.m_icontrol));
        m_node.m_icontrol= nullptr;
    }
    if (m_node.m_scontrol){
        zsock_destroy((zsock_t**)(&m_node.m_scontrol));
        m_node.m_scontrol= nullptr;
    }
    if (m_node.m_net){
        zsock_destroy((zsock_t**)(&m_node.m_net));
        m_node.m_net= nullptr;
    }
	return ERROR_BASE_SUCCEED;
}

unsigned int SeedCzmqServer::ZmqSetBeOpt() {
    return 0;
}

unsigned int SeedCzmqServer::ZmqSetAfOpt() {
    return 0;
}


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