【RPC】Apache Thrift系列详解 - 概述与入门
创始人
2025-05-28 04:37:09

文章目录

  • 前言
  • 正文
    • Thrift的技术栈
    • Thrift的特性
      • (一) 开发速度快
      • (二) 接口维护简单
      • (三) 学习成本低
      • (四) 多语言/跨语言支持
      • (五) 稳定/广泛使用
    • Thrift的数据类型
    • Thrift的协议
    • Thrift的传输层
    • Thrift的服务端类型
    • Thrift入门示例
      • (一) 编写Thrift IDL文件
      • (二) 新建Maven工程
  • 总结

前言

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

Thrift支持多种不同的编程语言,包括C++、Java、Python、PHP、Ruby等,本系列主要讲述基于Java语言的Thrift的配置方式和具体使用。

正文

Thrift的技术栈

Thrift对软件栈的定义非常的清晰, 使得各个组件能够松散的耦合, 针对不同的应用场景, 选择不同是方式去搭建服务。
在这里插入图片描述

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

  • 传输层(Transport Layer):传输层负责直接从网络中读取和写入数据,它定义了具体的网络传输协议;比如说TCP/IP传输等。

  • 协议层(Protocol Layer):协议层定义了数据传输格式,负责网络传输数据的序列化和反序列化;比如说JSON、XML、二进制数据等。

  • 处理层(Processor Layer):处理层是由具体的IDL(接口描述语言)生成的,封装了具体的底层网络传输和序列化方式,并委托给用户实现的Handler进行处理。

  • 服务层(Server Layer):整合上述组件,提供具体的网络线程/IO服务模型,形成最终的服务。

Thrift的特性

(一) 开发速度快

通过编写RPC接口Thrift IDL文件,利用编译生成器自动生成服务端骨架(Skeletons)和客户端桩(Stubs)。从而省去开发者自定义和维护接口编解码、消息传输、服务器多线程模型等基础工作。

  • 服务端:只需要按照服务骨架即接口,编写好具体的业务处理程序(Handler)即实现类即可。
  • 客户端:只需要拷贝IDL定义好的客户端桩和服务对象,然后就像调用本地对象的方法一样调用远端服务。

(二) 接口维护简单

通过维护Thrift格式的IDL(接口描述语言)文件(注意写好注释),即可作为给Client使用的接口文档使用,也自动生成接口代码,始终保持代码和文档的一致性。且Thrift协议可灵活支持接口的可扩展性。

(三) 学习成本低

因为其来自Google Protobuf开发团队,所以其IDL文件风格类似Google Protobuf,且更加易读易懂;特别是RPC服务接口的风格就像写一个面向对象的Class一样简单。
初学者只需参照:thrift.apache.org/,一个多小时就可以理解Thrift IDL文件的语法使用。

(四) 多语言/跨语言支持

Thrift支持C++、 Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk等多种语言,即可生成上述语言的服务器端和客户端程序。
对于我们经常使用的Java、PHP、Python、C++支持良好,虽然对iOS环境的Objective-C(Cocoa)支持稍逊,但也完全满足我们的使用要求。

(五) 稳定/广泛使用

Thrift在很多开源项目中已经被验证是稳定和高效的,例如Cassandra、Hadoop、HBase等;国外在Facebook中有广泛使用,国内包括百度、美团小米、和饿了么等公司。
在这里插入图片描述

Thrift的数据类型

Thrift 脚本可定义的数据类型包括以下几种类型:

  1. 基本类型:

    • bool: 布尔值
    • byte: 8位有符号整数
    • i16: 16位有符号整数
    • i32: 32位有符号整数
    • i64: 64位有符号整数
    • double: 64位浮点数
    • string: UTF-8编码的字符串
    • binary: 二进制串
  2. 结构体类型:

    • struct: 定义的结构体对象
  3. 容器类型:

    • list: 有序元素列表
    • set: 无序无重复元素集合
    • map: 有序的key/value集合
  4. 异常类型:

    • exception: 异常类型
  5. 服务类型:

    • service: 具体对应服务的类

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模型上进行增强

Thrift入门示例

(一) 编写Thrift IDL文件

a). 下载0.10.0的Thrift IDL编译器,下载地址:http://thrift.apache.org/docs/install。 通过编译生成器生成.java接口的类文件。
在这里插入图片描述

b). 下载Windows安装环境的.exe文件,将thrift.exe的路径加入环境变量中。在Idea上安装Thrift编辑插件。
在这里插入图片描述

c). 编写hello.thrift的IDL文件:

service HelloWorldService {string say(1: string username)
}

d). 使用代码生成工具生成代码,执行以下命令:

thrift -gen java hello.thrift

e). 由于未指定代码生成的目标目录,生成的类文件默认存放在gen-java目录下。这里生成一个HelloWorldService.java类文件,文件大小超过数千行,下面截取一部分核心代码。

public class HelloWorldService {public interface Iface {public String say(String username) throws org.apache.thrift.TException;}public interface AsyncIface {public void say(String username, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;}public static class Client extends org.apache.thrift.TServiceClient implements Iface {public static class Factory implements org.apache.thrift.TServiceClientFactory {public Factory() {}public Client getClient(org.apache.thrift.protocol.TProtocol prot) {return new Client(prot);}public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {return new Client(iprot, oprot);}}public Client(org.apache.thrift.protocol.TProtocol prot) {super(prot, prot);}public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {super(iprot, oprot);}public String say(String username) throws org.apache.thrift.TException {send_say(username);return recv_say();}// 省略.....}public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {public static class Factory implements org.apache.thrift.async.TAsyncClientFactory {private org.apache.thrift.async.TAsyncClientManager clientManager;private org.apache.thrift.protocol.TProtocolFactory protocolFactory;public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {this.clientManager = clientManager;this.protocolFactory = protocolFactory;}public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {return new AsyncClient(protocolFactory, clientManager, transport);}}public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {super(protocolFactory, clientManager, transport);}public void say(String username, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {checkReady();say_call method_call = new say_call(username, resultHandler, this, ___protocolFactory, ___transport);this.___currentMethod = method_call;___manager.call(method_call);}// 省略.....}// 省略.....
}

对于开发人员而言,使用原生的Thrift框架,仅需要关注以下四个核心内部接口/类:Iface, AsyncIface, Client和AsyncClient。

  • Iface:服务端通过实现HelloWorldService.Iface接口,向客户端的提供具体的同步业务逻辑。
  • AsyncIface:服务端通过实现HelloWorldService.Iface接口,向客户端的提供具体的异步业务逻辑。
  • Client:客户端通过HelloWorldService.Client的实例对象,以同步的方式访问服务端提供的服务方法。
  • AsyncClient:客户端通过HelloWorldService.AsyncClient的实例对象,以异步的方式访问服务端提供的服务方法。

(二) 新建Maven工程

a). 新建maven工程,引入thrift的依赖,这里使用的是版本0.10.0。

  org.apache.thriftlibthrift0.10.0

b). 将生成类的HelloWorldService.java源文件拷贝进项目源文件目录中,并实现HelloWorldService.Iface的定义的say()方法。

HelloWorldServiceImpl.java

public class HelloWorldServiceImpl implements HelloWorldService.Iface {@Overridepublic String say(String username) throws TException {return "Hello " + username;}
}

c). 服务器端程序编写:
SimpleServer.java

public class SimpleServer {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(ServerConfig.SERVER_PORT);TServerSocket serverTransport = new TServerSocket(serverSocket);HelloWorldService.Processor processor =new HelloWorldService.Processor(new HelloWorldServiceImpl());TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();TSimpleServer.Args tArgs = new TSimpleServer.Args(serverTransport);tArgs.processor(processor);tArgs.protocolFactory(protocolFactory);// 简单的单线程服务模型 一般用于测试TServer tServer = new TSimpleServer(tArgs);System.out.println("Running Simple Server");tServer.serve();}
}

d). 客户端程序编写:
SimpleClient.java

public class SimpleClient {public static void main(String[] args) {TTransport transport = null;try {transport = new TSocket(ServerConfig.SERVER_IP, ServerConfig.SERVER_PORT, ServerConfig.TIMEOUT);TProtocol protocol = new TBinaryProtocol(transport);HelloWorldService.Client client = new HelloWorldService.Client(protocol);transport.open();String result = client.say("Leo");System.out.println("Result =: " + result);} catch (TException e) {e.printStackTrace();} finally {if (null != transport) {transport.close();}}}
}

e). 运行服务端程序,服务端在指定端口监听客户端的连接请求,控制台输出启动日志:
在这里插入图片描述

f). 运行客户端程序,客户端通过网络请求HelloWorldService的say()方法的具体实现,控制台输出返回结果:
在这里插入图片描述

这里使用的一个基于单线程同步的简单服务模型,一般仅用于入门学习和测试!

总结

本文对Thrift的概念做了相关介绍,体验了一番thrift程序如何编写!

相关内容

热门资讯

如家快捷酒店上海(如家快捷酒店... 本篇文章极速百科给大家谈谈如家快捷酒店上海,以及如家快捷酒店上海人民广场对应的知识点,希望对各位有所...
梅河口酒店(梅河口酒店排行榜)... 本篇文章极速百科给大家谈谈梅河口酒店,以及梅河口酒店排行榜对应的知识点,希望对各位有所帮助,不要忘了...
宇豪海逸酒店(宇豪海逸酒店地址... 本篇文章极速百科给大家谈谈宇豪海逸酒店,以及宇豪海逸酒店地址对应的知识点,希望对各位有所帮助,不要忘...
温州金球国豪大酒店(温州金球国... 本篇文章极速百科给大家谈谈温州金球国豪大酒店,以及温州金球国豪大酒店餐饮预订电话对应的知识点,希望对...
[数据分析与可视化] Pyth... 本文主要介绍GeoPandas的基本使用方法,以绘制简单的地图。GeoPandas是一...
stm32H7内部flash存... 目录一、慎用固件库1.HAL_FLASH_Program有问题,写入不正常2.采用直接...
厦门环岛路客栈(厦门环岛路客栈... 本篇文章极速百科给大家谈谈厦门环岛路客栈,以及厦门环岛路客栈图片对应的知识点,希望对各位有所帮助,不...
欣燕都连锁酒店(欣燕都连锁酒店... 本篇文章极速百科给大家谈谈欣燕都连锁酒店,以及欣燕都连锁酒店北京前门店对应的知识点,希望对各位有所帮...
大连火车站附近旅店(大连火车站... 本篇文章极速百科给大家谈谈大连火车站附近旅店,以及大连火车站附近旅店哪家有小姐对应的知识点,希望对各...
厦门至石家庄机票(厦门到石家庄... 今天给各位分享厦门至石家庄机票的知识,其中也会对厦门到石家庄机票查询进行解释,如果能碰巧解决你现在面...
Web系统优化实战 1. 课程介绍2. 系统优化原理 1.1. Web系统优化概述 1.1.1. 提高网站速度 1.1....
笨鸟学数据结构(绪论) 数据结构的定义按某种逻辑关系组织起来的一批数据,按一定的映象方式把它存放在计算机的存储...
经典卷积模型回顾24—利用模型... 模型剪枝是指在训练深度学习模型时将某些不重要的部分剪掉,以实现更快速、更高效的模型精度...
关于重庆通信学院的信息 重庆通... 本篇文章极速百科给大家谈谈重庆通信学院,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本...
新民到沈阳的火车(新民到沈阳的... 今天给各位分享新民到沈阳的火车的知识,其中也会对新民到沈阳的火车时间表和票价进行解释,如果能碰巧解决...
中国携程网(中国携程网上订票官... 本篇文章极速百科给大家谈谈中国携程网,以及中国携程网上订票官网对应的知识点,希望对各位有所帮助,不要...
全国各地旅游景点(全国各地旅游... 今天给各位分享全国各地旅游景点的知识,其中也会对全国各地旅游景点大全地图进行解释,如果能碰巧解决你现...
《MongoDB入门教程》第2... 本文将会介绍 MongoDB 复合索引的概念,以及如何创建复合索引。 复合索引 复合索...
Python 关键字globa... 变量作用域 一般在函数体外定义的变量成为全局变量,在函数内部定义的变量称为局部变量。 ...
力扣-《剑指offer》-链表... 目录 第一题:从尾到头打印链表 第二题:删除链表的节点 第三题ÿ...
上海七天快捷酒店(上海七天连锁... 本篇文章极速百科给大家谈谈上海七天快捷酒店,以及上海七天连锁酒店预订对应的知识点,希望对各位有所帮助...
临沂观塘温泉(临沂观塘温泉大酒... 今天给各位分享临沂观塘温泉的知识,其中也会对临沂观塘温泉大酒店进行解释,如果能碰巧解决你现在面临的问...
2min是多少时间 ,2min... 2min是多少时间 目录2min是多少时间 2min是多少时间2min是什么意思2min是多少时间2...
廊坊酒店预订(廊坊酒店多少钱一... 本篇文章极速百科给大家谈谈廊坊酒店预订,以及廊坊酒店多少钱一晚对应的知识点,希望对各位有所帮助,不要...
vuex学习笔记(一) 目录 一、Vuex的介绍 1、简介 2、通俗理解 二、安装,配置Vuex 1、安装 2...
c指针(二) 1.指针和指针变量的关系指针 就是内存的地址编号。指针变量:本质是变量 只是该变量 保...
【并发基础】join()方法底... 目录 一、简介 1.1 作用 1.2 join()方法和join(long timeout)方法的使...
Java操作Zookeeper... 1. Java操作ZooKeeper 引入jar包: org.apache.zoo...
北京宾馆预订(北京宾馆预订携程... 今天给各位分享北京宾馆预订的知识,其中也会对北京宾馆预订携程官网进行解释,如果能碰巧解决你现在面临的...
广州到重庆的火车票(广州到重庆... 今天给各位分享广州到重庆的火车票的知识,其中也会对广州到重庆的火车票价是多少进行解释,如果能碰巧解决...