Thrift第五課 應用模式以及運行異常
結構模型
1)調用RPC接口的過程中,參數是請求的結構信息,返回值是服務器的反饋信息
2)對於服務器的告警信息和系統公告信息,客戶端需要定時發送查詢的RPC接口,然後在RPC的接口返值
中攜帶反饋信息
局限性
測試代碼
short sThriftPort = 0;
std::string strThriftIP;
CSystemConfig::GetInstance().GetThriftServiceInfo(strThriftIP, sThriftPort);
boost::shared_ptr<UploadMessageServiceHandler> handler(new UploadMessageServiceHandler());
boost::shared_ptr<TProcessor> processor(new UploadMessageServiceProcessor(handler));
boost::shared_ptr<TServerTransport> serverTransport(new TServerSocket(sThriftPort));
boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
boost::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(10);
boost::shared_ptr<BoostThreadFactory> threadFactory(new BoostThreadFactory());
threadManager->threadFactory(threadFactory);
threadManager->start();
TThreadPoolServer server(processor, serverTransport, transportFactory, protocolFactory, threadManager);
server.serve();
在上述的服務器端進行客戶端請求的監聽,存在如下的問題
1 服務器端只有等待客戶端的連接,等待客戶端的請求發送,然後把應答的消息返回到客戶端,如果服務器端想主動發送消息
給客戶端,在當前的這種框架下是不可能實現的,必須調整當前的thrift的框架邏輯.
2 當客戶端沒有正常關閉套接字,服務器端會一直等待客戶端的請求,沒有機制確保服務器端知道客戶端已經丟棄當前的連接。
這種沒有客戶端發送心跳確保在線的機制,是否能夠滿足生產的需求,有待商榷
3 客戶端一般都是在NAT環境之後,所以客戶端無法開啟端口對服務器的推送消息進行接收,只有在客戶端主動連接服務器,
保持連接的通道,可以進行雙向通道的通信
4 服務器端不會主動關閉連接,關閉連接都是由客戶端進行的,如果有惡意的連接,耗盡所有的線程,導致拒絕服務的風險
2 服務器模式
客戶端也是服務器,需要啟動端口進行監聽服務器端消息的推送
局限性
客戶端需要開放端口進行監聽,如果客戶端部署在私有的網絡,通過NAT連接到公網的服務器,這一點目前單純依賴thrift框架無法實現
3 雙向通道模式
結構模型
雙向通道確實可以讓服務器端直接推送告警和系統公告信息給客戶端,但是thrift在這種應用結構中,不允許調用的RPC接口有任何的返回值,就類似於UDP的郵件的投遞,服務器端的反饋信息需要通過用RPC
發送給客戶端客戶端以一種類似回調的方式來獲取到反饋的信息
局限性
發送的請求,需要在回調函數中得到反饋信息,對於是否執行成功,客戶端需要等待
C#客戶端異常剖析
1)未將對象引用設置到對象的實例 原因:無法連接Thrift服務器
2)無法將數據寫入傳輸連接(遠程主機強迫關閉了一個現有的連接) 原因:Thrift服務器崩潰或者重啟,連接中斷
3)應用服務跟客戶端的代碼不一致:調用的目標發生了異常(無法將數據寫入傳輸連接: 你的主機中的軟件中止了一個已建立的連接)
C++接收代碼
類:class TDispatchProcessor : public TProcessor
函數:
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
void* connectionContext) {
std::string fname;
protocol::TMessageType mtype;
int32_t seqid;
in->readMessageBegin(fname, mtype, seqid);
if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) {
GlobalOutput.printf("received invalid message type %d from client",
mtype);
return false;
}
return dispatchCall(in.get(), out.get(), fname, seqid, connectionContext);
}
WireShark抓包可以看到發送的服務接口
Thrift第五課 應用模式以及運行異常