Thrift——入门Demo(Java)

概述


Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信。

Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。
那么它是如何实现使用不同的语言开发呢?
答案:一种关联客户端和服务端的中间语言。

这种语言就是IDL(Interface Description Language)。将这个IDL作为输入文件,编译器就可以生成代码(支持多种),即RPC客户端和服务器通信的无缝跨编程语言。

安装


下载官方链接:http://thrift.apache.org/download
将下载好的thrift-0.10.0 .exe文件命名为thrift .exe,放在D盘下的一个Thtift文件夹中,
为了更方便使用命令,将目录加入到系统Path路径下:

image

在cmd中输入:thrift -version ,查看是否安装配置成功

image

出现版本号,安装成功。

定义thrift——IDL文件


IDL文件有许多数据类型

  • 结构体类型: struct:定义公共的对象,类似于 C 语 言中的结构体定义,在 Java 中是一个 JavaBean
  • 容器类型:
          list:对应 Java 的 ArrayList
          set:对应 Java 的 HashSet
          map:对应 Java 的 HashMap
  • 异常类型: exception:对应 Java 的 Exception
  • 服务类型: service:对应服务的类

这里仅仅定义一个服务。
thrift定义服务相当于Java中创建Interface,创建的service通过代码生成命令生成客户端和服务端的框架代码。
定义形式如下(helloworld.thrift,注意后缀!):

1
2
3
4
5
6
namespace java com.test
service HelloWorldService{
string sayHello(1:string name)
}

——namespace 相当于Java中的package。

在 cmd中 输入命令: thrift -gen java helloworld.thrift

image

可以看到生成了一个名为gen-java的文件夹,其中就是生成的代码,打开后可以看到层级目录下有:

image

代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Autogenerated by Thrift Compiler (0.10.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
package com.test;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2017-07-18")
public class HelloWorldService {
public interface Iface {
public java.lang.String sayHello(java.lang.String name) throws org.apache.thrift.TException;
}

创建项目


创建一个Maven工程,引入依赖,可在Maven依赖中看到引入的相关Jar包

1
2
3
4
5
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.10.0</version>
</dependency>

服务端实现与启动


服务端相关操作的步骤如下:

  • 实现服务处理接口Impl
  • 创建TProcessor
  • 创建TServerTransport
  • 创建TProtocol
  • 创建TServer
  • 启动Server
服务端实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.test;
import org.apache.thrift.TException;
public class HelloWorldImpl implements HelloWorldService.Iface{
public HelloWorldImpl(){
}
public String sayHello(String name) throws TException {
return "Hi," +name + " welcome !";
}
}
服务端启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.test;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
public class HelloServer {
public static final int SERVER_PORT = 8090;
public void startServer(){
System.out.println("Server is Runing......");
TProcessor tprocessor = new HelloWorldService.Processor(new HelloWorldImpl());
//简单的单线程服务模型,一般用于测试
try {
TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
TServer.Args tArgs = new TServer.Args(serverTransport);
tArgs.processor(tprocessor);
tArgs.protocolFactory(new TBinaryProtocol.Factory());
TServer server = new TSimpleServer(tArgs);
server.serve();
} catch (Exception e) {
System.out.println("Server start error!");
e.printStackTrace();
}
}
public static void main(String[] args) {
HelloServer server = new HelloServer();
server.startServer();
}
}

运行上面的启动类,控制台输出:Server is Runing……

image

客户端启动


客户端步骤:
  • 创建Transport
  • 创建TProtocol
  • 基于TTransport和TProtocol创建 Client
  • 调用Client的相应方法
客户端启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.test;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
public class HelloClient {
public static final String SERVER_IP = "localhost";
public static final int SERVER_PORT = 8090;
public static final int TIMEOUT = 30000;
public void startClient(String userName){
TTransport transport = null;
try {
transport = new TSocket(SERVER_IP,SERVER_PORT,TIMEOUT);
//协议要和服务端一致
TProtocol protocol = new TBinaryProtocol(transport);
HelloWorldService.Client client = new HelloWorldService.Client(protocol);
transport.open();
String result = client.sayHello(userName);
System.out.println("Thrift client result is:"+result);
} catch (Exception e) {
System.out.println("client is error!");
}finally{
if(null != transport){
transport.close();
}
}
}
public static void main(String[] args) {
HelloClient client = new HelloClient();
client.startClient("Z Yong");
}
}
控制台输出: Thrift client result is: Hi,Z Yong welcome !

image

客户端成功收到了服务端返回的请求结果,通信完成