学习RPC框架-Thrift日志

前言

Thrift是一个轻量级、跨语言的远程服务调用框架,最初是由Facebook开发的,后面进入Apache开源项目。他通过自身的IDL中间语言,并借助代码生成引擎生成各种主流语言的RPC服务端/客户端模版代码。

Thrift 支持多种不同的变成语言。包括C++、Java、Python、PHP、Ruby等。

正文

Thrift软件栈分层从下向上分别为:传输层(Transport Layer)、协议层(Protocol Layer)、处理层(Processor Layer)和服务层(Server Layer)。

  • 传输层(Transport Layer):传输层负责直接从网络中读取写入数据,它定义了具体的网络传输协议;比如说TCP/IP传输等。
  • 协议层(Protocol Layer):协议层定义了数据传输格式,负责网络传输数据的序列化反序列化;比如说JSONXML二进制数据等。
  • 处理层(Processor Layer):处理层是由具体的IDL接口描述语言)生成的,封装了具体的底层网络传输序列化方式,并委托给用户实现的Handler进行处理。
  • 服务层(Server Layer):整合上述组件,提供具体的网络线程/IO服务模型,形成最终的服务。

特点:

​ 开发速度快
​ 接口维护简单
​ 多语言支持
​ 稳定、使用广泛

数据类型

IDL是一个典型的CS结构,使用与客户端和服务端使用不同语言的调用。
基本类型、特殊类型、集合类型

类型 标志 描述
基本类型 bool 布尔值
byte 8位有符号整数
i16 16位有符号整数
i32 32位有符号整数
i64 64位有符号整数
double 64位浮点数
string UTF-8编码的字符串
枚举类型 enum 枚举类型
结构体类型 struct 定义的结构体对象
容器类型 list 有序元素列表
set 无序不重复元素集合
map 无序的key/value集合
特殊类型 binary 二进制串
异常类型 exception 异常类型
服务类型 service 具体对应服务的类

struct有以下一些约束:

  • struct不能继承,但是可以嵌套,不能嵌套自己
  • 其成员都是有明确类型
  • 成员是被正整数编号过的,其中的编号使不能重复的,这个是为了在传输过程中编码使用
  • 成员分割符可以是逗号(,)或是分号(;),而且可以混用
  • 字段会有optional和required之分和protobuf一样,但是如果不指定则为无类型–可以不填充该值,但是在序列化传输的时候也会序列化进去,optional是不填充则不序列化,required是必须填充也必须序列化。
  • 每个字段可以设置默认值
  • 同一文件可以定义多个struct,也可以定义在不同的文件,进行include引入

下面来看看各类型是怎么定义的:

//命名空间-表示java代码会生成路径位org.surpass
namespace java org.surpass
//命名空间-表示python代码会生成路径位org.surpass
namespace py org.surpass

//定义一个实体
struct User {
   
    1:required i16 id;
    2:string name;
    3:optional bool isMan;
    4:i16 age = "18";
}

//定义一个实体
//required 表示该字段必须存在或者有值
//optional 表示可选
struct Teacher {
   
    1:required i16 id;
    2:string name;
    3:list<User> userList;
    4:set<User> userSet;
    5:map<i16, User> userMap;
}

//定义一个异常
exception BusException {
   
    1:i32 errorCode;
    2:string errorMsg;
}

//定义一个业务处理类
service Teach {
   
    list<User> getUserList(1:i16 teacherId);
    User getUser(1:string name);
    map<i16, User> getUserMap() throws (1:BusException e);
}


//定义一个枚举类
enum UserEnum {
   
    CLASS1 = 1;
    CLASS2 = 2;
}

那么我们如何根据thrift文件生成javapython 代码?

下载链接:https://thrift.apache.org/docs/install/

下载对应平台的thrift可执行文件,并加入到path环境变量中,这样在终端命令行中任何路径都能使用。

我们使用以下命令:

thrift -gen java gen.thrift
thrift -gen py gen.thrift

结果生成的文件就是这个样子:

org
    └─surpass
            BusException.java
            Teach.java
            Teacher.java
            User.java
            UserEnum.java

**文件解析:业务处理类 Teach.java **
Iface:服务端通过实现 HelloWorldService.Iface 接口,向客户端的提供具体的同步业务逻辑。
AsyncIface:服务端通过实现 HelloWorldService.Iface 接口,向客户端的提供具体的异步业务逻辑。
Client:客户端通过 HelloWorldService.Client 的实例对象,以同步的方式访问服务端提供的服务方法。
AsyncClient:客户端通过 HelloWorldService.AsyncClient 的实例对象,以异步的方式访问服务端提供的服务方法。

Teach 作为业务处理类,我们只要继承里面的接口并且实现方法,实现自己的处理逻辑即可。

//自己实现的接口逻辑
public class TeachImpl implements Teach.Iface {
   
		@Override
        public List<User> getUserList(short teacherId) throws TException {
   
            return new ArrayList<User>(){
   {
   
                add(new User());
            }};
        }

        @Override
        public User getUser(String name) throws TException {
   
            return new User((short) 1, name, (short) 20);
        }

        @Override
        public Map<Short, User> getUserMap() throws BusException, TException {
   
            return null;
        }
}

Thrift的协议

Thrift可以让用户选择客户端服务端之间传输通信协议的类别,在传输协议上总体划分为文本(text)和二进制(binary)传输协议。为节约带宽提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目/产品中的实际需求。常用协议有以下几种:

  • TBinaryProtocol:二进制编码格式进行数据传输
  • TCompactProtocol:高效率的、密集二进制编码格式进行数据传输
  • TJSONProtocol: 使用JSON文本的数据编码协议进行数据传输
  • TSimpleJSONProtocol:只提供JSON只写的协议,适用于通过脚本语言解析

Thrift的传输层

常用的传输层有以下几种:

  • TSocket:使用阻塞式I/O进行传输,是最常见的模式
  • TNonblockingTransport:使用非阻塞方式,用于构建异步客户端
  • TFramedTransport:使用非阻塞方式,按块的大小进行传输,类似于Java中的NIO

Thrift服务端类型

  • TSimpleServer:单线程服务器端,使用标准的阻塞式I/O
  • TThreadPoolServer:多线程服务器端,使用标准的阻塞式I/O
  • TNonblockingServer:单线程服务器端,使用非阻塞式I/O
  • THsHaServer:半同步半异步服务器端,基于非阻塞式IO读写和多线程工作任务处理
  • TThreadedSelectorServer:多线程选择器服务器端,对THsHaServer异步IO模型上进行增强

示例

服务端

public class TeachServer {
   

    public static void main(String[] args) throws TTransportException {
   
        TServerSocket socket = new TServerSocket(9111);

        Teach.Processor<TeachImpl> processor = new Teach.Processor<>(new TeachImpl());

        TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();

        TServer.Args arg = new TSimpleServer.Args(socket);
        arg.processor(processor);
        arg.protocolFactory(factory);

        TSimpleServer server = new TSimpleServer(arg);

        server.serve();

    }

}

客户端

public class TeachClient {
   

    public static void main(String[] args) throws TException {
   
        //由于在本机测试所以为localhoust,注意端口要一致
        TSocket tSocket = new TSocket("localhost", 9111);

        TBinaryProtocol tBinaryProtocol = new TBinaryProtocol(tSocket);

        Teach.Client client = new Teach.Client(tBinaryProtocol);

        tSocket.open();

        User user = client.getUser("张三");

        System.out.println(user);

    }
}

总结

今天先写到这里后续再补充。。。。。

相关推荐

  1. 学习RPC框架-Thrift

    2023-12-15 05:16:09       44 阅读
  2. 谷粒商城学习

    2023-12-15 05:16:09       10 阅读
  3. 5.13学习

    2023-12-15 05:16:09       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-15 05:16:09       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-15 05:16:09       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-15 05:16:09       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-15 05:16:09       20 阅读

热门阅读

  1. Retrofit上传文件到oss文件存储

    2023-12-15 05:16:09       36 阅读
  2. SQL区间

    2023-12-15 05:16:09       38 阅读
  3. ClickHouse(17)ClickHouse集成JDBC表引擎详细解析

    2023-12-15 05:16:09       36 阅读
  4. CentOS 7入门指南

    2023-12-15 05:16:09       39 阅读
  5. 使用工具 NVM来管理不同版本的 Node.js启动vue项目

    2023-12-15 05:16:09       37 阅读
  6. 第一周:AI产品经理跳槽准备工作

    2023-12-15 05:16:09       41 阅读
  7. 【Qt5】Qt Creator中CMake的qt5_wrap_ui函数

    2023-12-15 05:16:09       27 阅读