国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

淺談Thrift內(nèi)部實(shí)現(xiàn)原理

2019-11-11 07:39:21
字體:
供稿:網(wǎng)友
     Thrift由兩部分組成:編譯器(在compiler目錄下,采用C++編寫)和服務(wù)器(在lib目錄下),其中編譯器的作用是將用戶定義的thrift文件編譯生成對應(yīng)語言的代碼,而服務(wù)器是事先已經(jīng)實(shí)現(xiàn)好的、可供用戶直接使用的RPC Server(當(dāng)然,用戶也很容易編寫自己的server)。同大部分編譯器一樣,Thrift編譯器(采用C++語言編寫)也分為詞法分析、語法分析等步驟,Thrift使用了開源的flex和Bison進(jìn)行詞法語法分析(具體見thrift.ll和thrift.yy),經(jīng)過語法分析后,Thrift根據(jù)對應(yīng)語言的模板(在compiler/cpp/src/generate目錄下)生成相應(yīng)的代碼。對于服務(wù)器實(shí)現(xiàn)而言,Thrift僅包含比較經(jīng)典的服務(wù)器模型,比如單線程模型(TSimpleServer),線程池模型(TThreadPoolServer)、一個請求一個線程(TThreadedServer)和非阻塞模型(TNonblockingServer)等。本文將以C++為例進(jìn)行一個實(shí)例分析。

假設(shè)用戶編寫了以下Thrift文件:

struct LogInfo {

1: required string name,

2: optional string content,

}

service LogSender {

void SendLog(1:list<LogInfo> loglist);

}

用戶使用命令“thrift –gen cpp example.thrift”可生成C++代碼,該代碼包含以下文件:

example_constants.h

example_constants.cpp

example_types.h  //struct定義

example_types.cpp  //struct實(shí)現(xiàn)

LogSender.h  //service定義

LogSender.cpp  //service實(shí)現(xiàn)和LogSenderClient實(shí)現(xiàn)

LogSender_server.skeleton.cpp //一個實(shí)例RPC Server

用戶可以這樣編寫Client:

shared_ptr socket(new TSocket(“8.8.8.8″, 9090));

shared_ptr transport(new TBufferedTransport(socket));

shared_ptr PRotocol(new TBinaryProtocol(transport));

LogSenderClient client(protocol);

try {

transport->open();

vector<LogInfo> logInfos;

LogInfo logInfo(“image”, “10:9:0 visit:xxxxxx”);

logInfos.push_back(logInfo);

…..

client.SendLog(logInfos);

transport->close();

} catch (TException &tx) {

printf(“ERROR: %s/n”, tx.what());

}

為了深入分析這段代碼,我們看一下client.SendLog()函數(shù)的內(nèi)部實(shí)現(xiàn)(在LogSender.cpp中):

void LogSenderClient::SendLog(const std::vector<LogInfo> & loglist)

{

send_SendLog(loglist);

recv_SendLog();

}

void LogSenderClient::send_SendLog(const std::vector<LogInfo> & loglist)

{

int32_t cseqid = 0;

oprot_->writeMessageBegin(“SendLog”, ::apache::thrift::protocol::T_CALL, cseqid);

LogSender_SendLog_pargs args;

args.loglist = &loglist;

args.write(oprot_);

oprot_->writeMessageEnd();

oprot_->getTransport()->flush();

oprot_->getTransport()->writeEnd();

}

void LogSenderClient::recv_SendLog()

{

int32_t rseqid = 0;

std::string fname;

::apache::thrift::protocol::TMessageType mtype;

iprot_->readMessageBegin(fname, mtype, rseqid);

if (mtype == ::apache::thrift::protocol::T_EXCEPTION) {

…..

}

if (mtype != ::apache::thrift::protocol::T_REPLY) {

……

}

if (fname.compare(“SendLog”) != 0) {

……

}

LogSender_SendLog_presult result;

result.read(iprot_);

iprot_->readMessageEnd();

iprot_->getTransport()->readEnd();

return;

}

閱讀上面的代碼,可以看出,RPC函數(shù)SendLog()實(shí)際上被轉(zhuǎn)化成了兩個函數(shù):send_SendLog和recv_SendLog,分別用于發(fā)送數(shù)據(jù)和接收結(jié)果。數(shù)據(jù)是以消息的形式表示的,消息頭部是RPC函數(shù)名,消息內(nèi)容是RPC函數(shù)的參數(shù)。

我們再進(jìn)一步分析RPC Server端,一個server的編寫方法(在LogSender.cpp中)如下:

shared_ptr protocolFactory(new TBinaryProtocolFactory());

shared_ptr handler(new LogSenderHandler());

shared_ptr processor(new LogSenderProcessor(handler));

shared_ptr serverTransport(new TServerSocket(9090));

shared_ptr transportFactory(new TBufferedTransportFactory());

TSimpleServer server(processor,

serverTransport,

transportFactory,

protocolFactory);

printf(“Starting the server…/n”);

server.serve();

Server端最重要的類是LogSenderProcessor,它內(nèi)部有一個映射關(guān)系processMap_,保存了所有RPC函數(shù)名到函數(shù)實(shí)現(xiàn)句柄的映射,對于LogSender而言,它只保存了一個RPC映射關(guān)系:

processMap_[" SendLog"] = &LogSenderProcessor::process_SendLog;

其中,process_SendLog是一個函數(shù)指針,它的實(shí)現(xiàn)如下:

void LogSenderProcessor::process_SendLog(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot)

{

LogSender_SendLog_args args;

args.read(iprot);

iprot->readMessageEnd();

iprot->getTransport()->readEnd();

LogSender_SendLog_result result;

try {

iface_->SendLog(args.loglist);//調(diào)用用戶編寫的函數(shù)

} catch (const std::exception& e) {

……

}

oprot->writeMessageBegin(“SendLog”, ::apache::thrift::protocol::T_REPLY, seqid);

result.write(oprot);

oprot->writeMessageEnd();

oprot->getTransport()->flush();

oprot->getTransport()->writeEnd();

}

LogSenderProcessor中一個最重要的函數(shù)是process(),它是服務(wù)器的主體函數(shù),服務(wù)器端(socket server)監(jiān)聽到客戶端有請求到達(dá)后,會檢查消息類型,并檢查processMap_映射,找到對應(yīng)的消息處理函數(shù),并調(diào)用之(注意,這個地方可以采用各種并發(fā)模型,比如one-request-one-thread,thread pool等)。

通過上面的分析可以看出,Thrift最重要的組件是編譯器(采用C++編寫),它為用戶生成了網(wǎng)絡(luò)通信相關(guān)的代碼,從而大大減少了用戶的編碼工作。


上一篇:1057. 數(shù)零壹(20)

下一篇:0016 泛型

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 陈巴尔虎旗| 民勤县| 偃师市| 信丰县| 蒲江县| 南雄市| 定襄县| 青海省| 会泽县| 闸北区| 宜宾市| 司法| 集贤县| 宝坻区| 舒兰市| 信阳市| 忻城县| 广南县| 荔波县| 体育| 贺兰县| 绿春县| 鹤岗市| 甘孜县| 保靖县| 泗阳县| 隆子县| 金山区| 新郑市| 灵台县| 砚山县| 新宁县| 东丰县| 丽水市| 苏州市| 鲁山县| 秦安县| 本溪市| 大方县| 依兰县| 昭通市|