Thrift is a cross-language RPC service framework developed by Facebook (including gRPC). It uses IDL (Interface Description Language) files to define interfaces and data types. The compiler provided by Thrift compiles the interfaces into different Language codes. This enables cross-language invocation.

Base Types

Type Desc JAVA GO
i8 A signed 8-bit integer byte int8
i16 A signed 16-bit integer float int16
i32 A signed 32-bit integer int int32
i64 A signed 64-bit integer long int64
double 64-bit floating point number double float64
bool Boolean value boolean bool
string Text string (UTF-8 encoding) java.lang.String string

Special Types

Binary: an unencoded sequence of bytes, a special form of a string; This type is mainly used to facilitate JAVA calls in certain scenarios. The corresponding type is java.nio.ByteBuffer in JAVA and []byte in GO.

Containers

Type Desc JAVA GO remark
list<T> An ordered list of elements, allowing repetition java.util.List []T
set<T> An unordered list of elements with no repetition allowed java.util.Set []T GO has no set set instead of an array
map<K,V> Key-value structure data. The key cannot be repeated java.util.Map map[K] V

Tips: Generics must be specified when using container types, otherwise idL files cannot be compiled. Second, primitive types in generics are replaced by their corresponding wrapper types in the JAVA language.

Constant and type aliases (Const&&Typedef)

// Constant definition
const i32 MALE_INT = 1
const map<i32.string> GENDER_MAP = {1: "male".2: "female"}
// Some data types are longer and can be simplified with aliases
typedef map<i32.string> gmp
Copy the code

Enumeration (enum)

Some methods that need to limit the range of arguments can use enums, which are constructed data types.

  • Variables can only be assigned integers, which can be negative;
  • Variables can also be assigned using hexadecimal integers;
  • Variables are assigned from 0 by default;
  • Variable separators can be used (,) and (;) , can be mixed or neither; Proposal unification;
// Variable default assignments start at 0;
enum GenderEnum{
    UNKNOWN,/ / 0
    MALE,/ / 1female/ / 2
}
// The first variable is set to 1, and the following variables are incremented;
enum RoleEnum{
    WARIOR = 1.1 / / war
    MAGE,/ / 2 method
    WARLOCK,/ / lock 3
    PRIEST,Pastor / / 4
    DRUID// druid 5
}
Copy the code

Structs :id=struct

In daily development, basic types and collection types do not meet business needs; You can then customize types using the struct keyword, essentially equivalent to classes in OOP languages (such as Javabeans).

Note the following points when using struct:

  • Structs have no inheritance relationships and can include themselves in nested references (some articles say not nested);
  • Member fields are strongly typed (that is, explicitly typed) and cannot be duplicated;
  • The field number must be a positive integer plus a colon (for example, 1: I32 ID). The field number cannot be repeated or consecutive.
  • Member field separators can be used (,) and (;). , can be mixed or not used at all, for the convenience of reading and damn obsessive-compulsive disorder, suggested unity;
  • Fields can be decorated with optional and Required, and default is optional; The difference is that required fields must be passed in remote calls, whereas optional fields are serialized only when assigned.
  • Basic and enum fields can be assigned by default, but struct fields cannot.
  • Based on business domain division or design perspective, multiple structs can be defined in different IDL files, referenced by include “xxx.thrift”; Note That a struct introduced by include requires a filename prefix (n: xxx.DemoStruct DemoStruct). Thrift automatically completes the namespace defined in the thrift file during compilation.
/** * struct nested and include examples, note that the IDL file will not compile due to the wrong location, see "struct can not be bidirectional reference" below. * /
//guild.thrift
namespace java io.buman.guild
include "player.thrift" / / error
struct Guild {
    10: i32 id,/ / ID of the guild
    20: stringThe name,// Guild name
    30: player.Player president / / error
}
//player.thrift
namespace java io.buman.player
include "guild.thrift"

// Variable default assignments start at 0;
enum GenderEnum{
    UNKNOWN,/ / 0
    MALE,/ / 1female/ / 2
}

// The first variable is set to 1, and the following variables are incremented;
enum RoleEnum{
    WARIOR = 1.1 / / war
    MAGE,/ / 2 method
    WARLOCK,/ / lock 3
    PRIEST,Pastor / / 4
    DRUID// druid 5
}

struct Player {
    1: i32 id,
    2: required string name,
    3: required RoleEnum role,
    4: required GenderEnum gender = GenderEnum.UNKNOWN,
    5: Player cp,
    6: guild.Guild guild
}
Copy the code

Tips: When the field is decorated with required, the compiled JAVA code passes validate().

  public void validate(a) throws org.apache.thrift.TException {
    // check for required fields
    if (name == null) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'name' was not present! Struct: " + toString());
    }
    if (role == null) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'role' was not present! Struct: " + toString());
    }
    if (gender == null) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'gender' was not present! Struct: " + toString());
    }
    // check for sub-struct validity
    if(guild ! =null) { guild.validate(); }}Copy the code

Structs cannot be referenced bidirectionally

// Player. thrift references Guild. Thrfit, but the guild. Thrift then references playe.thrift. (base) buman@bogon % thrift --gen java player.thrift zsh: segmentation fault thrift --gen java player.thrift (base) buman@bogon % thrift --gen -v java player.thrift // Try again Scanning player.thrift with --verbose or -vfor includes
Scanning guild.thrift for includes
Scanning player.thrift for includes
Scanning guild.thrift for includes
Scanning player.thrift forincludes ... . zsh: segmentation fault thrift --gen java -v player.thriftCopy the code

Abnormal (Exceptions)

Thrift supports custom exceptions in services using the exception keyword, which is structurally equivalent to a structure. In this way, clients can better identify and handle service exceptions.

exception PlayerNotFoundException {
    1: i32 code = 400.2: string msg
}
Copy the code

Services :id=service

The service interface is defined with the Service keyword, which is a collection of named functions. Idl syntax is all about service definition.

  • Named functions have parameter lists and return value types. Parameter lists can be empty, and no return values are decorated with the void keyword.
  • The parameter list is similar to the definition of member fields in struct, and each parameter needs to be preceded by a positive integer + colon number, which can be discontinuous.
  • Parameter lists can use delimiters (,) and (;). , can be mixed or neither (freedom is sin); Be used to (,);
service PlayerService {

    /** * Player registration */
    Player signIn(1: Player player)

    /** * query all players */
    list<Player> queryAllPlayer()

    /** * Registered guild */
    guild.Guild registerGuild(1: guild.Guild guild)

    /**
     * 查询所有公会
     */
    list<guild.Guild> queryAllGuild()

    /** * add cp */ to the player
    Player addCp(1: i32 pid, 2: Player player) throws (1: PlayerNotFoundException e)

    /** * Players join the guild */
    Player joinGuild(1: i32 pid, 2: i32 gid) throws (1: PlayerNotFoundException e)
}
Copy the code

Tips: Note the syntax used by Exception, which also needs to be numbered.

The thrift compilation environment is installed

https://thrift.apache.org/download.html website to download installation

//macOS
brew install thrift
Copy the code

Idl file compilation

// Compile JAVA language files, default output to the current directory, generate gen- JAVA folder (gen-{compiled language}); Thrift --gen Java playler.thrift --gen Java guild. Thrift // Specifies the output directory thrift --gen Java -o target player.thrift thrift --gen java -o target guild.thriftCopy the code

Note that include structs in IDL files are not compiled, so you need to compile each IDL file separately.

The sample code

Github.com/bumangrowin…

reference

  • [1] the official documentation (https://thrift.apache.org/docs/types)