spp proxy 源码分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_17612199/article/details/80857246

spp proxy demo

#include "defaultproxy.h"

using namespace spp::proxy;

int main(int argc, char* argv[])
{
    CServerBase* proxy = new CDefaultProxy;
    proxy->run(argc, argv);
    delete proxy;
    return 0;
}

源码分析

spp_rpc/src/proxy/defaultproxy.h

namespace spp
{
    namespace proxy
    {
        class CDefaultProxy : public CServerBase, public CFrame
        {
        public:
            // 构造函数+析构函数

            // 实际运行函数
            void realrun(int argc, char* argv[]);

            // 服务容器类型

            // 获取接口地址
            unsigned GetListenIp(const char *intf);

            int loop();

            // 初始化配置
            int initconf(bool reload = false);

            //一些回调函数
            static int ator_recvdata(unsigned flow, void* arg1, void* arg2);    //必要
            static int ctor_recvdata(unsigned flow, void* arg1, void* arg2);    //必要
            static int ator_recvdata_v2(unsigned flow, void* arg1, void* arg2); //必要
            // ...非必要回调函数

            // 接受者 与controller通信
            CTCommu* ator_;

            // 连接者,共享内存队列,与worker通信
            map<int, CTCommu*> ctor_;

            //ip限制类型
            unsigned char iplimit_;

            //ip集合
            set<unsigned> iptable_;

            spp_handle_process_t local_handle;
        };
    }
}

spp_rpc/src/proxy/defaultproxy.cpp

void CDefaultProxy::realrun(int argc, char* argv[])
{
    //初始化配置
    SingleTon<CTLog, CreateByProto>::SetProto(&flog_);
    initconf(false);
    ix_->fstat_inter_time_ = 5; //5秒 统计一次框架信息
    time_t fstattime = 0;
    time_t montime = 0;
    static char statbuff[PROXY_STAT_BUF_SIZE];
    char* pstatbuff = (char*)statbuff;
    int bufflen = 0;
    char ctor_stat[1 << 16] = {0};
    int ctor_stat_len = 0;
    int processed = 0;

    while (true)
    {

        //轮询acceptor
        ator_->poll(processed == 0); // need sleep ?
        processed = 0;

        //轮询connector
        map<int, CTCommu*>::iterator it;
        for (it = ctor_.begin(); it != ctor_.end(); it++)
        {
            spp_global::set_cur_group_id(it->first);
            processed += it->second->poll(true); // block
        }

        if ( unlikely(get_time_s() - montime > ix_->moni_inter_time_) )
        {

            // 上报信息到ctrl进程
            CLI_SEND_INFO(&moncli_)->timestamp_ = get_time_s();
            moncli_.run();

            //输出监控统计信息
        }

        //检查quit信号
        if (unlikely(CServerBase::quit()))
        {

            int count = 20;
            while(count--)
            {
                for (it = ctor_.begin(); it != ctor_.end(); it++)
                {
                    it->second->poll(true); // block
                }
                usleep(20000);
            }
            break; // 20ms * 20
        }

        loop();
    }

    if (sppdll.spp_handle_fini != NULL)
        sppdll.spp_handle_fini(NULL, this);
}

当proxy接收到用户请求的回调处理,然后通知对应worker进行处理

int CDefaultProxy::ator_recvdata_v2(unsigned flow, void* arg1, void* arg2)
{
    blob_type* blob = (blob_type*)arg1;
    CDefaultProxy* proxy = (CDefaultProxy*)arg2;
    proxy->flog_.LOG_P_FILE(LOG_DEBUG, "flow:%u,blob len:%d\n", flow, blob->len);
    int total_len = blob->len;
    int processed_len = 0;
    int proto_len = -1;
    int ret = 0;
    int handle_exception = 0;

    while (blob->len > 0 && (proto_len = sppdll.spp_handle_input(flow, arg1, arg2)) > 0)
    {
        // 异常处理
        // ...

        //选取路由number
        unsigned route_no;

        if (!sppdll.spp_handle_route)
        {
            //如果spp_handle_route没有实现,只选取第一个
            route_no = 1;
        }
        else
        {
            // 0x7FFF 为了去掉GROUPID并兼容
            route_no = sppdll.spp_handle_route(flow, arg1, arg2) & 0x7FFF;
        }

        blob_type sendblob;

        // 分配空间

        if (data != NULL)
        {
            // 获取sendblob
            memcpy(data, blob->data, proto_len);
            memcpy(data + proto_len, blob->extdata, sizeof(TConnExtInfo));
            sendblob.data = data;
            sendblob.len = proto_len + sizeof(TConnExtInfo);
        }

        // 根据router_no选取相应的worker,将data写入与该worker相对应的共享内存
        map<int, CTCommu*>::iterator iter;
        if ((iter = proxy->ctor_.find(route_no)) != proxy->ctor_.end())
        {
            MONITOR(MONITOR_PROXY_TO_WORKER);
            ret = iter->second->sendto(flow, &sendblob, NULL);
        }

        //异常处理

        blob->data += proto_len;
        blob->len -= proto_len;
    }

    // ...
}

当proxy接收到ctl的心跳询问,会主动回包维持心跳

int CDefaultProxy::ctor_recvdata(unsigned flow, void* arg1, void* arg2)
{
    blob_type* blob = (blob_type*)arg1;
    CDefaultProxy* proxy = (CDefaultProxy*)arg2;

    // 维持心跳
    int ret = proxy->ator_->sendto(flow, arg1, NULL);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_17612199/article/details/80857246
SPP