preface

Thrift is a lightweight, cross-language framework for remote service invocation, originally developed by Facebook and later made its way into the Apache open source project. It generates RPC server/client template code for various major languages through its own IDL intermediate language and with the help of a code generation engine.

Thrift supports many different programming languages, including C++, Java, Python, PHP, and Ruby. This series focuses on how to configure and use Thrift based on the Java language.

The body of the

Thrift’s technology stack

Thrift’s definition of software stack is very clear, so that components can be loosely coupled and services can be constructed in different ways according to different application scenarios.

The Thrift software stack consists of the Transport Layer, Protocol Layer, Processor Layer, and Server Layer from bottom to top.

  • Transport Layer: The Transport Layer is responsible for reading and writing data directly from the network. It defines the specific network Transport protocol. Such as TCP/IP transmission.

  • Protocol Layer: The Protocol Layer defines the data transmission format and is responsible for serialization and deserialization of data transmitted over the network. Examples include JSON, XML, binary data, and so on.

  • Processor Layer: The Processor Layer is generated by the specific IDL (Interface Description Language), encapsulates the specific low-level network transmission and serialization modes, and delegates the processing to the user-implemented Handler.

  • Server Layer: Integrate the above components to provide a concrete network thread /IO service model to form the final service.

The characteristics of Thrift

(1) Fast development speed

By writing RPC interface Thrift IDL files, compile generators automatically generate server Skeletons and client Stubs. In this way, it saves the developers from defining and maintaining interface codec, message transmission, server multi-threaded model and other basic work.

  • Server: You only need to follow theService skeletonnamelyinterface, write a good specificBusiness handler(Handler),The implementation classCan.
  • Client: Only copyIDLA definedThe client pileandThe service object, and then invokes the remote service as if it were calling a method on a local object.

(2) The interface is easy to maintain

The IDL (Interface Description Language) file in Thrift format can be used as the interface document for clients and the interface code is automatically generated to maintain the consistency between the code and the document. Thrift protocol can flexibly support interface extensibility.

(3) Low learning cost

Because it comes from the Google Protobuf development team, the IDL file has a similar style to Google Protobuf and is much easier to read and understand. In particular, the style of the RPC service interface is as simple as writing an object-oriented Class.

For starters, just look at this thrift.apache.org/ and you’ll understand the syntax of Thrift IDL files in just over an hour.

(IV) Multi-language/cross-language support

Thrift supports C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, node. js, Smalltalk, and many other languages.

It has good support for Java, PHP, Python and C++ that we often use. Although it has poor support for Objective-C(Cocoa) in the iOS environment, it fully meets our requirements.

(v) Stable/widely used

Thrift has been verified to be stable and efficient in many open source projects, such as Cassandra, Hadoop, HBase, etc. Facebook is widely used in foreign countries, including Baidu, Meituan Xiaomi, and Ele. me.

Data type of Thrift

The Thrift scripts can define the following types of data:

  1. Basic types:
    • Boolean: the Boolean value
    • Byte: an 8-bit signed integer
    • I16: a 16-bit signed integer
    • I32:32-bit signed integer
    • I64:64-bit signed integer
    • Double: 64-bit floating point number
    • String: utF-8 encoded character string
    • Binary: a binary string
  2. Structure type:
    • Struct: structure object defined
  3. Container type:
    • List: a list of ordered elements
    • Set: Unordered collection of non-repeating elements
    • Map: an ordered set of keys and values
  4. Exception type:
    • Exception: indicates the exception type
  5. Service type:
    • Service: service class

The agreement of Thrift

Thrift allows the user to select the types of transmission protocols between the client and server. The transmission protocols are generally divided into text and binary. To save bandwidth and improve transmission efficiency, binary transmission protocols are generally used, and text-based protocols are sometimes used based on the actual requirements of the project or product. Common protocols are as follows:

  • TBinaryProtocol: Transmits data in binary encoding format
  • TCompactProtocol: an efficient, dense binary encoding format for data transfer
  • Use TJSONProtocol:JSONThe textData encoding protocol for data transmission
  • TSimpleJSONProtocol: Provided onlyJSONJust writeThe agreement applies throughScript language parsing

Thrift’s transport layer

The following transport layers are commonly used:

  • Use TSocket:The block typeI/OTransmission is the most common mode
  • TNonblockingTransport: Uses a non-blocking mode for building asynchronous clients
  • Use TFramedTransport:Non-blocking modeAccording to theThe size of the blockTo transmit, something like thatJavaIn theNIO

The server type of Thrift

  • TSimpleServer:Single threadServer side, using standardThe block typeI/O
  • TThreadPoolServer:multithreadingServer side, using standardThe block typeI/O
  • TNonblockingServer:Single threadServer side, usedNon-blocking typeI/O
  • THsHaServer:Half synchronous and half asynchronousServer-side, based onNon-blocking typeIOReading and writing andmultithreadingJob task processing
  • TThreadedSelectorServer:Multithreaded selectorServer side, rightTHsHaServerinasynchronousIOThe model is enhanced

Thrift Primer example

(1) Compile Thrift IDL files

A). The download 0.10.0 Thrift IDL compiler, download address: http://thrift.apache.org/docs/install. Java interface class files generated by compiling the generator.

B). Download the. Exe file of the Windows installation environment and add the path of thrift. Install the Thrift editing plug-in on Idea.

C). Compile the IDL file of Hello. thrift:

service HelloWorldService {
  string say(1: string username)
}
Copy the code

D). Use the code generation tool to generate the code and execute the following command:

thrift -gen java hello.thrift
Copy the code

E). Because the target directory for code generation is not specified, the generated class files are stored in the gen-java directory by default. A helloWorldService.java class file is generated that is over several thousand lines in size. Here is a snippet of the core code.

public class HelloWorldService {
    public interface Iface {
        public String say(String username) throws org.apache.thrift.TException;
    }

    public interface AsyncIface {
        public void say(String username, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws org.apache.thrift.TException;
    }

    public static class Client extends org.apache.thrift.TServiceClient implements Iface {
        public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
            public Factory(a) {}public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
                return new Client(prot);
            }

            public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
                return newClient(iprot, oprot); }}public Client(org.apache.thrift.protocol.TProtocol prot) {
            super(prot, prot);
        }

        public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
            super(iprot, oprot);
        }

        public String say(String username) throws org.apache.thrift.TException {
            send_say(username);
            return recv_say();
        }
        / / to omit...
    }

    public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
        public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
            private org.apache.thrift.async.TAsyncClientManager clientManager;
            private org.apache.thrift.protocol.TProtocolFactory protocolFactory;

            public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
                this.clientManager = clientManager;
                this.protocolFactory = protocolFactory;
            }

            public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
                return newAsyncClient(protocolFactory, clientManager, transport); }}public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
            super(protocolFactory, clientManager, transport);
        }

        public void say(String username, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws org.apache.thrift.TException {
            checkReady();
            say_call method_call = new say_call(username, resultHandler, this, ___protocolFactory, ___transport);
            this.___currentMethod = method_call;
            ___manager.call(method_call);
        }
        / / to omit...
    }
    / / to omit...
}
Copy the code

For developers using the native Thrift framework, there are only four core internal interfaces/classes to focus on: Iface, AsyncIface, Client, and AsyncClient.

  • Iface:The service sideBy implementingHelloWorldService.IfaceInterface to theThe clientProvide specificsynchronousBusiness logic.
  • AsyncIface:The service sideBy implementingHelloWorldService.IfaceInterface to theThe clientProvide specificasynchronousBusiness logic.
  • Client:The clientthroughHelloWorldService.ClientTo the instance object ofsynchronousThe way ofAccessing the serverThe service method provided.
  • AsyncClient:The clientthroughHelloWorldService.AsyncClientTo the instance object ofasynchronousThe way ofAccessing the serverThe service method provided.

(II) New Maven project

A). Create a Maven project and introduce thrift dependencies, using version 0.10.0 here.

  <dependency>
      <groupId>org.apache.thrift</groupId>
      <artifactId>libthrift</artifactId>
      <version>0.10.0</version>
  </dependency>
Copy the code

B). Copy the generated class helloWorldService.java source file into the project source file directory, and implement the say() method defined by helloWorldService.iface.

HelloWorldServiceImpl.java

public class HelloWorldServiceImpl implements HelloWorldService.Iface {
    @Override
    public String say(String username) throws TException {
        return "Hello "+ username; }}Copy the code

C). Server-side programming:

SimpleServer.java

public class SimpleServer {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(ServerConfig.SERVER_PORT);
        TServerSocket serverTransport = new TServerSocket(serverSocket);
        HelloWorldService.Processor processor =
                new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldServiceImpl());

        TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();
        TSimpleServer.Args tArgs = new TSimpleServer.Args(serverTransport);
        tArgs.processor(processor);
        tArgs.protocolFactory(protocolFactory);

        // A simple single-threaded service model is commonly used for testing
        TServer tServer = new TSimpleServer(tArgs);
        System.out.println("Running Simple Server"); tServer.serve(); }}Copy the code

D). Client programming:

SimpleClient.java

public class SimpleClient {
    public static void main(String[] args) {
        TTransport transport = null;
        try {
            transport = new TSocket(ServerConfig.SERVER_IP, ServerConfig.SERVER_PORT, ServerConfig.TIMEOUT);
            TProtocol protocol = new TBinaryProtocol(transport);
            HelloWorldService.Client client = new HelloWorldService.Client(protocol);
            transport.open();

            String result = client.say("Leo");
            System.out.println("Result =: " + result);
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null! = transport) { transport.close(); }}}}Copy the code

E). Run the server program, the server listens to the connection request of the client at the specified port, and the console outputs startup logs:

F). Run the client program, the client requests the specific implementation of say() method of HelloWorldService through the network, and the console output returns the result:

The simple service model used here is one step based on a single line and is generally only used for beginner learning and testing!

conclusion

This article introduces the concept of Thrift and shows how to write Thrift programs.

A link to the

  1. Apache Thrift Series Details (I) – Overview and Introduction

  2. Apache Thrift series details (II) – Network services Model

  3. Apache Thrift – Serialization mechanism


Welcome to pay attention to the technical public number: Zero one Technology Stack

This account will continue to share learning materials and articles on back-end technologies, including virtual machine basics, multithreaded programming, high-performance frameworks, asynchronous, caching and messaging middleware, distributed and microservices, architecture learning and progression.