thrift rpc 的 api 入门学习

170 阅读3分钟

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);
        }
    }
}