1 概览
+-------------------------------------------+
| Server |
| (single-threaded, event-driven etc) |
+-------------------------------------------+
| Processor |
| (compiler generated) |
+-------------------------------------------+
| Protocol |
| (JSON, compact etc) |
+-------------------------------------------+
| Transport |
| (raw TCP, HTTP etc) |
+-------------------------------------------+
复制代码
我们把他换成自己容易理解的方式:

2 分层解析
2.1 Transport(传输层)
传输层为网络的读写提供了一个简单的抽象。这使得Thrift能够将底层传输与系统的其他部分解耦(例如,序列化/反序列化)。
接口支持的方法:
可传输的底层协议:
2.2 Protocol(协议层)
协议层抽象定义了一种机制来将内存中的数据结构映射到连线格式。换句话说,协议指定数据类型如何使用底层的Transport对自己进行编码/解码。因此,协议实现控制编码方案并负责(反)序列化。这种意义上的协议的一些例子包括JSON、XML、纯文本、压缩二进制文件等。
接口支持的方法:
写(编码)方法:
- writeMessageBegin(name, type, seq)
- writeMessageEnd()
- writeStructBegin(name)
- writeStructEnd()
- writeFieldBegin(name, type, id)
- writeFieldEnd()
- writeFieldStop()
- writeMapBegin(ktype, vtype, size)
- writeMapEnd()
- writeListBegin(etype, size)
- writeListEnd()
- writeSetBegin(etype, size)
- writeSetEnd()
- writeBool(bool)
- writeByte(byte)
- writeI16(i16)
- writeI32(i32)
- writeI64(i64)
- writeDouble(double)
- writeString(string)
读(解码)方法:
- name, type, seq = readMessageBegin()
readMessageEnd() - name = readStructBegin()
readStructEnd() - name, type, id = readFieldBegin()
readFieldEnd() - k, v, size = readMapBegin()
readMapEnd() - etype, size = readListBegin()
readListEnd() - etype, size = readSetBegin()
readSetEnd() - bool = readBool()
- byte = readByte()
- i16 = readI16()
- i32 = readI32()
- i64 = readI64()
- double = readDouble()
- string = readString()
支持的编码协议:
2.3 Processor(处理器层)
处理器封装了从输入流读取数据和向输出流写入数据的能力。输入和输出流由Protocol对象表示。
接口方法样例:
interface TProcessor {
bool process(TProtocol in, TProtocol out) throws TException
}
复制代码
2.4 Server(应用服务层)
一个服务器集合了上面描述的所有不同的特性:
- 创建一个运输
- 为传输创建输入/输出协议
- 创建基于输入/输出协议的处理器
- 等待传入的连接,并将它们交给处理器
3 thrift安装
下载页:thrift.apache.org/download
下载Windows版本:

下载后可以直接使用,或者放在固定文件设置环境变量

4 Go使用thrift
4.1 项目结构和依赖安装

依赖安装:
go get -u github.com/apache/thrift
复制代码
4.2 编写thrift文件并编译
namespace go hello
struct HelloReq {
1: string msg;
}
struct HelloResp {
1: string msg;
}
service HelloService {
//返回值类型 方法名(参数序号:参数类型 参数名);
HelloResp Hello(1: HelloReq req);
}
复制代码
编译:
thrift -r --gen go hello.thrift
复制代码
4.3 服务端代码
type HelloServiceImpl struct {
}
func (e *HelloServiceImpl) Hello(ctx context.Context, req *hello.HelloReq) (*hello.HelloResp, error) {
fmt.Printf("message from client: %v\n", req.GetMsg())
res := &hello.HelloResp{
Msg: "Hi Client ~",
}
return res, nil
}
func main() {
transport, err := thrift.NewTServerSocket(":9898")
if err != nil {
panic(err)
}
handler := &HelloServiceImpl{}
processor := hello.NewHelloServiceProcessor(handler)
//也可以选择Framed传输协议,但是必须确保服务端和客户端的传输协议一致
transportFactory := thrift.NewTBufferedTransportFactory(1024)
//应对Java客户端
//factory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
//可以选择任意一种编码协议,但是必须确保服务端和客户端的编码协议一致
protocolFactory := thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{}) //布尔参数strictRead, strictWrite,读和写时是否加入版本校验。
server := thrift.NewTSimpleServer4(
processor,
transport,
transportFactory,
//factory,
protocolFactory,
)
if err := server.Serve(); err != nil {
panic(err)
}
}
复制代码
4.4 客户端代码
func main() {
transportFactory := thrift.NewTBufferedTransportFactory(1024)
//可以选择任意一种通信协议,但是必须确保服务端和客户端的通信协议一致
protocolFactory := thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{}) //布尔参数strictRead, strictWrite,读和写时是否加入版本校验。
//Java服务端
//factory := thrift.NewTCompactProtocolFactoryConf(&thrift.TConfiguration{})
transport:= thrift.NewTSocketConf("127.0.0.1:9898",&thrift.TConfiguration{})
useTransport, err := transportFactory.GetTransport(transport)
client := hello.NewHelloServiceClientFactory(useTransport, protocolFactory)
if err := transport.Open(); err != nil {
fmt.Fprintln(os.Stderr, "Error opening socket to 127.0.0.1:9898", " ", err)
os.Exit(1)
}
defer transport.Close()
req := &hello.HelloReq{Msg: "Hello Server ~"}
res, err := client.Hello(context.Background(), req)
if err != nil {
log.Println("Echo failed:", err)
return
}
log.Println("response:", res.Msg)
}
复制代码
4.5 验证

5 Java使用thrift
5.1 项目结构和依赖

依赖:
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.15.0</version>
</dependency>
复制代码
5.2 编写thrift文件并编译
namespace java hello
struct HelloReq {
1: string msg;
}
struct HelloResp {
1: string msg;
}
service HelloService {
HelloResp Hello(1: HelloReq req);
}
复制代码
编译:
thrift -r --gen java hello.thrift
复制代码
注意:编译完成之后需要将生成的.java文件放到项目结构中的对应位置。
5.3 服务端代码
public class ThriftServer {
public static void main(String[] args) throws TTransportException {
//设置服务器端口 TNonblockingServerSocket-非堵塞服务模型
TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8899);
//参数设置
THsHaServer.Args arg = new THsHaServer.Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4);
//处理器
//PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl());
HelloService.Processor<HelloServiceImpl> processor = new HelloService.Processor<>(new HelloServiceImpl());
arg.protocolFactory(new TCompactProtocol.Factory());
arg.transportFactory(new TFramedTransport.Factory());
arg.processorFactory(new TProcessorFactory(processor));
TServer server = new THsHaServer(arg);
System.out.println("Thrift 服务端启动成功");
server.serve();
}
}
//Handler
class HelloServiceImpl implements HelloService.Iface {
@Override
public HelloResp Hello(HelloReq req) throws TException {
System.out.println(req.msg);
return new HelloResp("Hello Client ~");
}
}
复制代码
5.4 客户端代码
public class ThriftClient {
public static void main(String[] args) throws TException {
TTransport transport = new TFramedTransport(new TSocket("localhost", 8899), 600);
TProtocol protocol = new TCompactProtocol(transport);
HelloService.Client client = new HelloService.Client(protocol);
transport.open();
String msg = client.Hello(new HelloReq("Hi Server ~")).msg;
System.out.println(msg);
transport.close();
}
}
复制代码
6 使用thrift进行Java和Go的远程通信
例如Java做客户端:
public class ThriftClientGo {
public static void main(String[] args) throws TTransportException {
TTransport transport = new TFramedTransport(new TSocket("127.0.0.1", 9898), 8000);
TBinaryProtocol binaryProtocol = new TBinaryProtocol(transport);
HelloService.Client client = new HelloService.Client(binaryProtocol);
try {
transport.open();
String msg = client.Hello(new HelloReq("Hi Server~")).msg;
System.out.println(msg);
}catch (Exception ex){
throw new RuntimeException(ex.getMessage(),ex);
}finally {
transport.close();
}
}
}
复制代码
参考文章:
thrift.apache.org/docs/concep…
thrift.apache.org/docs/concep…
blog.csdn.net/pengpengzho…