Thrift

要使用的时候首先应该先编辑一个thrift文件,其中包括结构体和服务的定义。

结构的定义

struct User{
    1:required string userId
    2:required i64 balance
    3:optinal string name
}

如果变量有默认值,可以直接写在定义文件里:

struct User {
    1: strubg uid
    2: i64  balance = 0
    3: map<i16,string> map
}
  1. 基本类型(括号内为对应的Java类型):

    • bool(boolean): 布尔类型(TRUE or FALSE)
    • byte(byte): 8位带符号整数
    • i16(short): 16位带符号整数
    • i32(int): 32位带符号整数
    • i64(long): 64位带符号整数
    • double(double): 64位浮点数
    • string(String): 采用UTF-8编码的字符串
  2. 除了上面提到的基本数据类型,Thrift还支持以下容器类型:

    • list(java.util.ArrayList)
    • set(java.util.HashSet)
    • map(java.util.HashMap)

服务的定义

include "helloworld.thrift"
namespace java com.core

service Base{
    string helloworld()
}

service Core{
    string transfer(1:string fromId,2:string toId,  3:i64 amount)
    int64 add(1:i64 number1,2:i64 number2)
}

在这个core.thrift文件里定义的Core这个service继承了Base这个service,其中namespace决定了生成的java文件将会放在哪个包内。

服务的实现

如果要单独生成某个thrift文件的指定语言版本代码,输入以下命令

thrift --gen <language> <Thrift filename>

如果要递归地将其include的thrift文件也生成,则使用如下命令

thrift -r --gen <language> <Thrift filename>

对于上面所示的文件,使用的命令为 thrift --gen java core.thrift
则会生成一个文件名为Core的文件,此文件中有一个为Iface的接口,实现此接口必须实现thrift文件里定义的方法。其他内容是为了thrift能正常调用的逻辑,这个文件不能进行修改。
在实际使用中,新建一个类名为CoreImpl实现Core.Iface,在这里我们将实现transfer和add两个方法的具体逻辑。这样就已经写完了thrift调用服务的准备工作,下面涉及到如何启动服务和调用服务。

服务的启动

传输通信协议

Thrift 可以让用户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为文本 (text) 和二进制 (binary) 传输协议,为节约带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目 / 产品中的实际需求。常用协议有以下几种:

  • TBinaryProtocol —— 二进制编码格式进行数据传输
  • TCompactProtocol —— 高效率的、密集的二进制编码格式进行数据传输
  • TJSONProtocol —— 使用 JSON 的数据编码协议进行数据传输
  • TSimpleJSONProtocol —— 只提供 JSON 只写的协议,适用于通过脚本语言解析

服务端和客户端必须使用同一种传输通信协议

传输层

常用的传输层有以下几种:

  • TSocket —— 使用阻塞式 I/O 进行传输,是最常见的模式,使用TServerSocket
  • TFramedTransport —— 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO,使用TNonblockingServerTransport
  • TNonblockingTransport —— 使用非阻塞方式,用于构建异步客户端
服务端类型

常见的服务端类型有以下几种:

  • TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O
  • TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O
  • TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O
Server与Client

下面是简单的使用TBinaryProtocol通信和使用Tsocket以及服务端类型为TThreadPoolServer的情况:
Core的Server

 public static void main(String[] args) { 
    try { 
        TServerSocket serverTransport = new TServerSocket(9999); //设置服务端口            
        Factory proFactory = new TBinaryProtocol.Factory();  //设置通信协议             
        TProcessor processor = new Core.Processor<Core.Iface>(CoreImpl); //关联处理器服务
        TThreadPoolServer.Args serverArgs = (new TThreadPoolServer.Args(serverTransport)).processor(processor);
        serverArgs.protocolFactory(proFactory);//填充启动参数
        TServer server = new TThreadPoolServer(serverArgs);
        server.serve(); 
    } catch (TTransportException e) { 
        e.printStackTrace(); 
    } 
} 

Core的Client

public static void main(String[] args) { 
    try { 
        TTransport transport = new TSocket("localhost", 9999); 
        transport.open(); 
        TProtocol protocol = new TBinaryProtocol(transport);//设置传输协议 
        Core.Client client = new Core.Client(protocol); 
        client.transfer("1","2",1); 
        transport.close(); 
    } catch (TTransportException e) { 
        e.printStackTrace(); 
    } catch (TException e) { 
        e.printStackTrace(); 
    } 
} 
非阻塞式异步

to be continue

推荐阅读更多精彩内容