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;
}
转自:https://blog.youkuaiyun.com/qq_17612199/article/details/80857246