天天看點

Thrift在C++中的使用thrift優缺點thrift檔案定義代碼生成client端代碼server端代碼編譯和運作

thrift優缺點

優點

官網:

https://thrift.apache.org/

Thrift是一個跨語言的服務部署架構,最初由Facebook于2007年開發,2008年進入Apache開源項目。

Thrift通過一個中間語言(IDL, 接口定義語言)來定義RPC的接口和資料類型,然後通過一個編譯器生成不同語言的代碼(目前支援C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代碼負責RPC協定層和傳輸層的實作。

Thrift實際上是實作了C/S模式,通過代碼生成工具将接口定義檔案生成伺服器端和用戶端代碼(可以為不同語言),進而實作服務端和用戶端跨語言的支援。使用者在Thirft描述檔案中聲明自己的服務,這些服務經過編譯後會生成相應語言的代碼檔案,然後使用者實作服務(用戶端調用服務,伺服器端提服務)便可以了。其中protocol(協定層, 定義資料傳輸格式,可以為二進制或者XML等)和transport(傳輸層,定義資料傳輸方式,可以為TCP/IP傳輸,記憶體共享或者檔案共享等)被用作運作時庫。

Thrift支援二進制,壓縮格式,以及json格式資料的序列化和反序列化。這讓使用者可以更加靈活的選擇協定的具體形式。更完美的是,協定是可自由擴充的,新版本的協定,完全相容老的版本!

缺點

極其缺少文檔,隻能通過讀thrift代碼充分的使用thrift,洽洽這是一件有樂趣的事情。

性能

Thrift在C++中的使用thrift優缺點thrift檔案定義代碼生成client端代碼server端代碼編譯和運作

在CompactProtocol情況下性能和ProtoBuffer相當,

BinaryProtocol情況下性能是ProtoBuffer的60%左右。

thrift檔案定義

namespace cpp example
struct Book_Info {
       1: i32 book_id,
       2: string book_name,
       3: string book_author,
       4: double book_price,
       5: string book_publisher,
}
namespace cpp example
include "book.thrift"
service BookServlet {
        bool Sender(1: list<book.Book_Info> books);
        oneway void Sender2(1: list<book.Book_Info> books);
}      

代碼生成

book.thrift

/usr/bin/thrift --gen cpp book.thrift      

thrift會在gen-cpp下面生成對應的cpp檔案:

├── book_constants.cpp
├── book_constants.h
├── book_types.cpp
└── book_types.h      

rpc.thrift

/usr/bin/thrift --gen cpp rpc.thrift      
├── BookServlet.cpp
├── BookServlet.h
├── BookServlet_server.skeleton.cpp
├── rpc_constants.cpp
├── rpc_constants.h
├── rpc_types.cpp
└── rpc_types.h      

client端代碼

#include "gen-cpp/BookServlet.h"
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/protocol/TBinaryProtocol.h>
using namespace apache::thrift;
using namespace apache::thrift::transport;
using namespace apache::thrift::protocol;
using namespace example;
int main(int argc, char** argv) {
  boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
  boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
  boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
  example::BookServletClient client(protocol);
  try {
      transport->open();
      std::vector<Book_Info> books;
      books.push_back(Book_Info());
      Book_Info &t0 = *books.rbegin();
      t0.book_name = "bookname0";
      books.push_back(Book_Info());
      Book_Info &t1 = *books.rbegin();
      t1.book_name = "bookname1";
      client.Sender(books);
      transport->close();
  } catch (TException &tx) {
      printf("ERROR: %s\n", tx.what());
  }
  printf("the end\n");
  return 0;
}      

server端代碼

#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <iostream>
#include "gen-cpp/BookServlet.h"
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace example;
class BookServletHandler : virtual public BookServletIf {
public:
    BookServletHandler() {}
    bool Sender(const std::vector<Book_Info> & books) {
        typedef  std::vector<Book_Info>::const_iterator Itr;
        for (Itr i = books.begin(); i != books.end(); ++i) {
            std::cout<<i->book_name<<std::endl;
        }
    }
    void Sender2(const std::vector<Book_Info> & books) {
        printf("Sender2\n");
    }
};
int main(int argc, char **argv) {
  boost::shared_ptr<BookServletHandler> handler(new BookServletHandler());
  boost::shared_ptr<TProcessor> processor(new BookServletProcessor(handler));
  boost::shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));
  boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}      

編譯和運作

g++ client.cpp gen-cpp/book_constants.cpp gen-cpp/BookServlet.cpp gen-cpp/book_types.cpp -lthrift  -o client
g++ server.cpp gen-cpp/book_constants.cpp gen-cpp/BookServlet.cpp gen-cpp/book_types.cpp -lthrift  -o server