thrift rpc 的 api 介绍
thrift 中要发起 rpc 调用需要通过 TTransport 来实现网络传输,TProtocol 来实现协议的序列化与反序列化,然后就是业务处理 TProcessor 来完成
TTransport 接口
他的实现的类如下:
- 阻塞 IO
- TSocket
- 非阻塞 IO
- TNonblockingSocket
- 含有封针的 API 主要可以解决半包黏包的问题,他主要是解决的压缩以后的数据的半包黏包问题
- TFramedTransport
TProtocol 接口
他主要就是解决的网络的协议和序列化以及反序列化的问题。
他的实现方式:
- 二进制
- TBinaryProtocol 普通的二进制协议
- TCompactProtocol 可以进一步压缩的二进制协议,他需要和 TFramedTransport 配合使用
- JSON 文本的方式
- TJSONProtocol
TProcessor 接口
他主要解决的是服务端如何处理请求的问题。相当于一个整合,要把 TTransport + TProtocol 的的数据和 业务代码做整合
TServer 接口
同步服务,异步服务,但线程 ,多线程 这个主要是用于服务端使用
案例
主要是使用 idl 语言来定义服务接口和传输对象以及异常信息,然后使用 thrift --gen 来生成我们需要的语言的代码,然后呢结合我们的业务代码,来使用实现客户端和服务端的交互
定义 idl
// 定义命名空间,类似于我们在 java 中的包名
namespace java com.thrift.demo
// 定义 struct
struct UserInfo {
1: string name,
2: i16 age,
3: string description,
4: i64 id
}
exception UserNotFountException {
1: string message
}
// 服务接口定义
service UserService {
UserInfo getUserInfoByUserId(1: i64 userId) throws (1: UserNotFountException notFound)
}
可以了以后我们可以使用 thrift --gen java user.thrift 这样就可以根据我们刚刚自己定义 idl 生成相对应的 java 代码,(为什么是 java 呢,因为我们这里指定的 gen 语言类型为 java,也可以生产 py 或者 go)这里生存代码以后,因为我们使用的是 maven 所以他会默认去读取 sec/java 目录下面的代码,这个时候我们需要 copy 刚刚生存的代码到 对应的目录然后引入一下的 pom 的 dependence 即可,至于版本号根据我的测试一般是跟自己安装的 thrift 工具版本一直即可
<dependency>
<groupId>com.rpc</groupId>
<artifactId>thrift-rpc-common</artifactId>
<version>${thrift.version}</version>
</dependency>
服务端代码
对服务端的接口做实现
接口的实现其实就是对我们刚刚 idl 语言实现的接口做实现,不过可能略有不同的是我们在实现的时候需要遵循 thrift 的规范来做实现,它是以内部类门面的方式来做的 *.IFace,其实对于自定义的实现就是简单直接的实现即可,无需关注太多
public class UserServiceImpl implements UserService.Iface {
@Override
public UserInfo getUserInfoByUserId(long userId) throws UserNotFountException {
System.out.println("获取用户信息");
return new UserInfo();
}
}
服务端的核心代码
public class ThriftServer {
public static void main(String[] args) {
// transport
TServerTransport serverTransport = new TServerSocket(8899);
// protocol
TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
// processor
UserService.Processor processor = new UserService.Processor(new UserServiceImpl());
// server
TServer server = new TSimpleServer(new Args(serverTransport).protocolFactory(protocolFactory).processor(processor));
server.serve();
}
}
客户端代码
所有的 rpc 框架的实现中都默认的遵循了一个规则,那就是想调用本地方法一样调用远端的服务,这个规则,在 thrift,hessian。grpc,openfeign 都如此
public class ThriftClient {
public static void main(String[] args) {
TTransport tTransport = new TSocket("localhost", 8899);
TProtocol protocol = new TBinaryProtocol(tTransport);
UserService.Client client = new UserService.Client(protocol);
try {
tTransport.open();
System.out.println(client.getUserInfoByUserId(1L));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}