1、前言
Apache Thrift是个远程服务调用框架,目前应用较广,它有如下优点:
1. IDL接口描述
2. 跨语言支持,如定义好接口后,可以支持多种语言的开发,如C++、Java、Python、PHP、Ruby、Perl等等,在多语言的环境下,有较大优势。
以下从应用角度,介绍个完整的demo,来实现client和server间的通信交互。
2、准备工作
1. 下载安装thrift:
以mac下的终端为例:( - linux下的安装类似,可以用yum、apt-get等,还可从源码编译安装(不建议该方式),请自行google、不再赘述)
thrift安装:brew install thrift
2. Java相关环境准备:
1. 下载jdk,并配置环境变量
2. 下载java IDE(集成开发环境)eclipse
以上安装网上资料很多,此处不详介绍。
3. 配置maven环境
为方便依赖包下载,可考虑用maven来管理依赖包 --
手动安装依赖包的,可考虑跳过这一小节。
1)maven下载:步骤参考该贴的讲解:http://blog.youkuaiyun.com/jiuqiyuliang/article/details/45390313
2)eclipse 中集成maven
~/.bash_profile 中添加MAVEN_HOME ,然后export 到PATH 中,在source ~/.bash_profile 文件使其生效
查看是否加载成功:mvn -version
在eclipse 中安装maven 插件:Help --> Install New Software ,然后输入 HTTP 地址http://m2eclipse.sonatype.org/sites/m2e
下载jar 包操作:在 pom.xml中添加依赖包后,选中pom.xml,右键选择“Maven install”,之后到.m2文件夹下查看安装好的jar包
3、Thrift实例讲解 - JAVA
在Eclipse中添加一个maven项目(依赖包不需要maven来下载的,直接添加普通package即可)
1. 定义服务接口
thrift采用IDL服务接口方式:
step1:编写thrift接口文件
demo.thrift:
namespace java com.test.thriftTry
service demo{
void sayHello(1:i64 id,2:string name,3:i32 age);
}
其中com.test.thriftTry是eclipse中建立的package,截图如下:
step2:使用thrift工具编译,自动生成接口声明代码文件。
该文件包含:1)thrift文件中描述的服务接口定义,即xxx.Iface接口;2)封装服务调用的底层通信细节,包括客户端的调用逻辑、以及服务端的处理逻辑。
编译命令:
thrift --gen java demo.thrift
将生成的gen-java下的demo.java move到eclipse的package下(参考上截图)
2. 实现服务处理接口impl
demo.java可理解成接口声明文件,在impl文件里实现接口细节。
demoimpl.java:
package com.test.thriftTry;
import java.util.Date;
import org.apache.thrift.TException;
public class demoImpl implements demo.Iface{
@Override
public void sayHello(long id,String name, int age) {
if (id == 1){
System.out.println("first id ACCESS --- " + new Date());
System.out.println("id: "+id+" name: "+name+" age: "+age+"\n");
}else if(name.length() < 3){
System.out.println("second id ACCESS -- " + new Date());
System.out.println("id: "+id+" name: "+name+" age: "+age+"\n");
}else{
System.out.println("third id ACCESS -- " + new Date());
System.out.println("id: "+id+" name: "+name+" age: "+age+"\n");
}
}
}
其中thrift文件中定义的sayHello API接口在这里实现。
3. 服务端代码实现
服务端代码基本步骤:
1)创建定义ServerSocket端口2)创建Processor3)创建TProtocol4)创建server5)启动server
代码细节参考如下
tServer.java
package com.test.thriftTry;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TBinaryProtocol.Factory;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import com.test.thriftTry.demo.Processor;
public class tServer {
public void startServer(){
try {
TServerSocket sts = new TServerSocket(8111);
demo.Processor pros = new Processor(new demoImpl());
Factory pf = new TBinaryProtocol.Factory(true, true);
Args args = new Args(sts);
args.processor(pros);
args.protocolFactory(pf);
TServer server = new TThreadPoolServer(args);
server.serve();
} catch (TTransportException e) {
e.printStackTrace();
}
}
public static void main(String [] args){
tServer ts = new tServer();
ts.startServer();
}
}
4. 客户端代码实现
客户端代码基本步骤:
1. 创建Transport2. 创建TProtocol3. 创建Client4. 调用Client
代码细节参考如下
tClient.java
package com.test.thriftTry;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import com.test.thriftTry.demo.sayHello_args;
public class tClient {
public void startClient() throws InterruptedException{
TTransport ts = new TSocket("localhost",8111);
TProtocol pto = new TBinaryProtocol(ts);
demo.Client client = new demo.Client(pto);
try {
ts.open();
client.sayHello(1,"jack", 30);
Thread.sleep(3000);
client.sayHello(2,"lucy", 5);
Thread.sleep(3000);
client.sayHello(3,"jetty", 29);
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException{
tClient tc = new tClient();
tc.startClient();
}
}
5. 代码执行
1. 启动server:eclipse中选中"tServer.java",右键选择“Run as” -> "Java Application"
注意重启的话,需杀掉之前的进程,否则会报端口占用的错误。
2. 启动client:eclipse中选中"tClient.java",右键选择“Run as” -> "Java Application"
项目结构图、执行结果截图如下,
6. 其它 - pom.xml配置
用maven下载依赖包时,pom.xml配置如下:
主要是thrift和slf4j的jar包下载地址
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.9.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
依赖包的地址配置和版本可到mvn官网查找:http://mvnrepository.com/
其中slf4j-nop是为了解决执行时的报错:SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
4、写在最后
本文给了个thrift tcp请求的基本构建实例。
在该实例基础上还可以做扩展,如thrift文件添加自定义struct结构类型、server端增加DB访问的支持、多线程的支持等等。
end