1. Overview
This document uses the C ++ language as an example to introduce how thrift RPC is used, including object serialization and deserialization, data transmission, and information exchange.
This document uses an example to describe the transmission (reporting logs or reports) function. This example runs through this article and covers thrift definitions, code generation, and thrift class descriptions, client compiling method, server compiling method, etc.
For Thrift Architecture Analysis, refer:Thrift Architecture.
For how to write Thrift files, refer:Thrift user guide.
2. Example description
Suppose we want to use thrift RPC to complete a data transmission task. The data format and PRC interface are described in a thrift file, as follows:
(1) book. thrift, which is used to describe the thrift interface of book Information
1234567891011121314151617 |
//book.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, } |
(2) rpc. thrift: RPC interface used by the client to transmit data (Report logs or reports) to the server
12345678910111213 |
//rpc.thrift 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); } |
Note: The thrift file defines a service, which contains two interfaces. The server needs to implement these two interfaces to provide services to the client. Among them, the first interface function is blocking, that is, it must wait for the server to return the value before continuing, and the other declaration is of the oneway type (the return value is void ), this function is non-blocking and does not have to wait for the returned results after data is sent to the server. However, when using this function, you must consider the server's affordability and adjust the sending frequency appropriately.
3. Correspondence between the Thrift file and the generated code
Each thrift file generates four files: $ {thrift_name} _ constants. h, $ {thrift_name} _ constants. cpp, $ {thrift_name} _ types. h, $ {thrift_name} _ types. cpp
For thrift files containing services, two additional files are generated: $ {service_name}. h, $ {service_name}. cpp.
For thrift files containing services, an available server pile is generated: $ {service_name}. _ server. skeleton. cpp.
For the example in this article, the following files will be generated:
Book_constants.hbook_constants.cpp
Book_types.hbook_types.cpp
Rpc_constants.hrpc_constants.cpp
Rpc_types.hrpc_types.cpp
BookServlet. hBookServlet. cpp
BookServlet_server.skeleton.cpp
4. Thrift class Introduction
The Thrift code package (located in thrift-0.6.1/lib/cpp/src) has the following directories:
Concurrency: database for concurrency and clock management
Processor: Processor-related classes
Protocal: Protocal related class
Transport: transport-related classes
Server: server-related classes
4.1Transport class (how is transmitted ?)
Responsible for data transmission. There are several available classes:
TFileTransport: a file (log) transmission class that allows the client to send files to the server and allow the server to write received data to the file.
THttpTransport: Data Transmission over Http
TSocket: uses TCP Socket for data transmission
TZlibTransport: transfers data after compression, or decompress the received data.
The following categories are mainly used to decorate the above categories (using the decorative mode) to improve transmission efficiency.
TBufferedTransport: buffer the data operated by a Transport object, that is, the data is read from the buffer for transmission, or the data is directly written to the buffer.
TFramedTransport: similar to TBufferedTransport, it also buffer related data and supports sending and receiving of fixed-length data.
TMemoryBuffer: reads and writes data from a buffer.
4.2Protocol class (what is transmitted ?)
Responsible for data encoding, mainly including the following available classes:
TBinaryProtocol: binary encoding
TJSONProtocol: JSON Encoding
TCompactProtocol: dense binary encoding
TDebugProtocol: organizes data in a readable manner.
4.3Server class (providing service for clients)
TSimpleServer: a simple single-threaded server used for testing.
TThreadPoolServer: multi-thread server with standard blocking IO
TNonblockingServer: a multi-thread server that uses non-blocking IO. TFramedTransport must use this type of server.
5. Object serialization and deserialization
The Protocol in Thrift is responsible for data encoding. Therefore, Protocol-related objects can be used for serialization and deserialization.
Because Object serialization and deserialization do not design transmission-related issues, you can use TBinaryProtocol and TMemoryBuffer as follows:
(1) Use thrift for Object serialization
// Serialize the object and save it to str
123456789101112131415 |
template < typename Type> void Object2String(Type& object, string &str) { shared_ptr<TMemoryBuffer> membuffer( new TMemoryBuffer()); shared_ptr<TProtocol> protocol( new TBinaryProtocol(membuffer)); object.write(protocol.get()); str.clear(); str = membuffer.getBufferAsString(); } |
(2) Use thrift for object deserialization
123456789101112131415 |
// Deserialize the objects saved in str and save them to the object template < typename Type> void String2Object(string& buffer, Type &object) { shared_ptr<TMemoryBuffer> membuffer( new TMemoryBuffer( reinterpret_cast <uint*>(buffer.data()))); shared_ptr<TProtocol> protocol( new TBinaryProtocol(membuffer)); object.read(protocol.get()); } |
6. Write the client and server
6.1 client code writing
The Methods written by the Client are as follows:
(1) define TTransport and set the transmission mode (such as socket and http) for your client ).
(2) define Protocal, encapsulate TTransport in Decorator mode, and set the encoding format (such as binary and JSON) for your data)
(3) instantiate the client object and call the service interface.
Note: If you define a service named $ {server_name} in the thrift file, an object named $ {server_name} Client is generated. For example, in my example, thrift automatically generates a class called BookServletClient. The code on the Client side is written as follows:
123456789101112131415161718192021222324252627282930313233 |
# Include "gen-cpp/BookServlet. h" // This header file must be included. // Its header file, other using namespace ....... int main( int argc, char ** argv) { shared_ptr<TTransport> socket( new TSocket( "localhost" , 9090)); shared_ptr<TTransport> transport( new TBufferedTransport(socket)); shared_ptr<TProtocol> protocol( new TBinaryProtocol(transport)); example::BookServletClient client(protocol); try { transport->open(); vector<example::Book_Info> books; …... client.Sender(books); // RPC function, which calls the function at the serve end transport->close(); } catch (TException &tx) { printf ( "ERROR: %s\n" , tx.what()); } } |
6.2Server-side code writing
(1) define a TProcess, which is a class automatically generated by thrift according to the user-defined thrift file.
(2) Use TServerTransport To Get A TTransport
(3) Use TTransportFactory to convert the original transmission to an appropriate application for transmission (typically using TBufferedTransportFactory)
(4) use TProtocolFactory to create an input and output for TTransport
(5) create a TServer object (single thread, you can use TSimpleServer; For multithreading, you can use TThreadPoolServer or TNonblockingServer) and call its server () function.
Note: thrift generates a simple server code (pile) for each thrift file with service. In this example, thrift generates BookServlet_server.skeleton.cpp, users can implement their own functions on the basis of this file.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
#include "gen-cpp/BookServlet.h" #include <protocol/TBinaryProtocol.h> #include <server/TSimpleServer.h> #include <transport/TServerSocket.h> #include <transport/TBufferTransports.h> using namespace ::apache::thrift; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; using namespace ::apache::thrift::server; using boost::shared_ptr; using namespace example; class BookServletHandler : virtual public BookServletIf { public : BookServletHandler() { // Your initialization goes here } // You need to implement this interface bool Sender( const std::vector<example::Book_Info> & books) { // Your implementation goes here printf ( "Sender\n" ); } // You need to implement this interface void Sender2( const std::vector<example::Book_Info> & books) { // Your implementation goes here printf ( "Sender2\n" ); } }; int main( int argc, char **argv) { int port = 9090; shared_ptr<BookServletHandler> handler( new BookServletHandler()); shared_ptr<TProcessor> processor( new BookServletProcessor(handler)); shared_ptr<TServerTransport> serverTransport( new TServerSocket(port)); shared_ptr<TTransportFactory> transportFactory( new TBufferedTransportFactory()); shared_ptr<TProtocolFactory> protocolFactory( new TBinaryProtocolFactory()); TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); server.serve(); return 0; } |
7. Summary
So far, all three articles on the thrift framework have been completed, including:
(1) Thrift framework introduction:Thrift framework Introduction
(2) Thrift file compiling method:Thrift User Guide
(3) Thrift RPC usage:Use Thrift RPC to write programs
The open-source RPC framework similar to thrift also has google's protocal buffer. Although it supports fewer languages, it is more efficient and has received more and more attention.
Because thrift has been open-source for a long time and has been tested for a long time, many systems prefer thrift, such as Hadoop and Cassandra.
Appendix: Comparison between thrift and protocal buffer
From the above comparison, we can see that thrift is superior to "rich features", while protocal buffer is superior to "document-based. In specific implementation, they are very similar. They all use unique Integers to mark field fields, which makes adding and deleting fields and does not destroy the existing code.
The biggest difference between them is that thrift supports the complete client/server RPC framework, while protocal buffer only produces interfaces. The specific implementation requires a lot of work.
In addition, from the serialization performance comparison, Protocal Buffer is far better than thrift, specific can refer to: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb? Ca = drs-tp4608.
8. References
(1) http://stuartsierra.com/2008/07/10/thrift-vs-protocol-buffers
(2) Thrift: Scalable Cross-Language Services Implementation. Mark Slee, Aditya Agarwal and Marc kwiatkoski. Facebook
Thrift Website: http://thrift.apache.org/
(4) Protocal Buffer Website:
Http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/overview.html
Original article, reprinted Please note:Reposted from Dong's blog
Link:Http://dongxicheng.org/search-engine/thrift-rpc/