当前位置: 首页 > news >正文

【RPC】Apache Thrift系列详解 - 概述与入门

文章目录

  • 前言
  • 正文
    • 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<String> 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<Client> {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<AsyncClient> {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<String> 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。

  <dependency><groupId>org.apache.thrift</groupId><artifactId>libthrift</artifactId><version>0.10.0</version></dependency>

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<HelloWorldService.Iface>(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程序如何编写!

相关文章:

【RPC】Apache Thrift系列详解 - 概述与入门

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

class03:MVVM模型与响应式原理

目录一、MVVM模型二、内在1. 深入响应式原理2. Object.entries3. 底层搭建一、MVVM模型 MVVM&#xff0c;即Model 、View、ViewModel。 Model > data数据 view > 视图&#xff08;vue模板&#xff09; ViewModel > vm > vue 返回的实例 > 控制中心, 负责监听…...

[Spring学习]08 @Resource和@Autowired注解的区别

目录前言一、Resource和Autowired注解的身世1、Resource注解2、Autowired注解3、常见的三种依赖注入方式及区别1. Filed注入2. Setter注入3. Constructor注入4. 三种依赖注入方式的区别二、Resource和Autowired注解的区别三、Resource和Autowired注解的推荐用法前言 当我们在属…...

前端开发神器VS Code安装教程

✅作者简介&#xff1a;CSDN一位小博主&#xff0c;正在学习前端 &#x1f4c3;个人主页&#xff1a;白月光777的CSDN博客 &#x1f4ac;个人格言&#xff1a;但行好事&#xff0c;莫问前程 安装VS CodeVS Code简介VS Code安装VS Code汉化结束语&#x1f4a1;&#x1f4a1;&…...

【Hive进阶】-- Hive SQL、Spark SQL和 Hive on Spark SQL

1.Hive SQL 1.1 基本介绍概念Hive由Facebook开发&#xff0c;用于解决海量结构化日志的数据统计&#xff0c;于2008年贡献给 Apache 基金会。Hive是基于Hadoop的数据仓库工具&#xff0c;可以将结构化数据映射为一张表&#xff0c;提供类似SQL语句查询功能本质&#xff1a;将Hi…...

搭建自己的直播流媒体服务器SRS,以及SRS+OBS直播推拉流使用及配置

一、前言 目前&#xff0c;全球直播带货什么的&#xff0c;成为主流&#xff0c;那如何自己搭建一个直播服务器呢。首先需要一个流媒体服务器&#xff0c;搭建流媒体有很多种方式&#xff0c;如下&#xff1a; 流媒体解决方案 Live555 &#xff08;C&#xff09;流媒体平台框…...

Node.js-----使用express写接口

使用express写接口 文章目录使用express写接口创建基本的服务器创建API路由模块编写GET接口编写POST接口CROS跨域资源共享1.接口的跨域问题2.使用cros中间件拒绝跨域问题3.什么是cros4.cros的注意事项5.cros请求的分类JSONP接口1.回顾jsonp的概念和特点2.创建jsonp接口的注意事…...

【Linux修炼】16.共享内存

每一个不曾起舞的日子&#xff0c;都是对生命的辜负。 共享内存一.共享内存的原理二.共享内存你的概念2.1 接口认识2.2演示生成key的唯一性2.3 再谈key三.共享资源的查看3.1 如何查看IPC资源3.2 IPC资源的特征3.3 进程之间通过共享内存进行关联四.共享内存的特点五.共享内存的内…...

JAVA进阶 —— Stream流

目录 一、 引言 二、 Stream流概述 三、Stream流的使用步骤 1. 获取Stream流 1.1 单列集合 1.2 双列集合 1.3 数组 1.4 零散数据 2. Stream流的中间方法 3. Stream流的终结方法 四、 练习 1. 数据过滤 2. 数据操作 - 按年龄筛选 3. 数据操作 - 演员信息要求…...

Linux基础命令大全(上)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…...

嵌入式 串口通信

目录 1、通信的基本概念 1.1 串行通信 1.2 并行通信 2、串行通信的特点 2.1 单工 2.2 半双工 2.3 全双工 3、串口在STM32的引脚 4、STM32的串口的接线 4.1 STM32的串口1和电脑通信的接线方式 4.2 单片机和具备串口的设备连接图 5、串口通信协议 6、串口通信…...

C语言函数调用栈

栈溢出&#xff08;stack overflow&#xff09;是最常见的二进制漏洞&#xff0c;在介绍栈溢出之前&#xff0c;我们首先需要了解函数调用栈。 函数调用栈是一块连续的用来保存函数运行状态的内存区域&#xff0c;调用函数&#xff08;caller&#xff09;和被调用函数&#xf…...

【高阶数据结构】红黑树

文章目录1. 使用场景2. 性质3. 结点定义4. 结点旋转5. 结点插入1. 使用场景 Linux进程调度CFSNginx Timer事件管理Epoll事件块的管理 2. 性质 每一个节点是红色或者黑色根节点一定是黑色每个叶子节点是黑色如果一个节点是红色&#xff0c;那么它的两个儿子节点都是黑色从任意…...

网络协议分析期末复习(二)

目录 12. 端口的定义及常见应用对应的端口号 13. UDP协议概述 14.UDP数据报格式及各字段意义 15. UDP-Lite协议概述 16. TCP数据报格式及各字段意义 17. TCP连接建立及协商参数的过程 18. TCP连接释放过程 19. 路由协议分类及各类的具体协议 20. 路由算法常用的度量 2…...

【C++】STL简介 及 string的使用

文章目录1. STL简介1.1 什么是STL1.2 STL的版本1.3 STL的六大组件2. string类的使用2.1 C语言中的字符串2.2 标准库中的string类2.3 string类的常用接口说明1. string类对象的常见构造2. string类对象的容量操作3. string类对象的修改操作4. resize和reserve5. 认识迭代器&…...

MySQL事务详解

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;Spring事务和MySQL事务详解 ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&#xff0c;欢迎你的加入: …...

ChatGPT背后的技术和多模态异构数据处理的未来展望——我与一位资深工程师的走心探讨

上周&#xff0c;我和一位从业三十余年的工程师聊到ChatGPT。 作为一名人工智能领域研究者&#xff0c;我也一直对对话式大型语言模型非常感兴趣&#xff0c;在讨论中&#xff0c;我向他解释这个技术时&#xff0c;他瞬间被其中惊人之处所吸引&#x1f64c;&#xff0c;我们深…...

iOS-砸壳篇(两种砸壳方式)

CrackerXI砸壳呢&#xff0c;当时你要是使用 frida-ios-dump 也是可以的&#xff1b; https://github.com/AloneMonkey/frida-ios-dump frida-ios-dump: 代码中需要更改的&#xff1a;手机中的内网ip 密码 等 最后放到我的砸壳路径里&#xff1a; python dump.py -l查看应用…...

linux 基础

1.Shell 命令的格式如下&#xff1a;command -options [argument]command: Shell 命令名称。options&#xff1a; 选项&#xff0c;同一种命令可能有不同的选项&#xff0c;不同的选项其实现的功能不同。argument&#xff1a; Shell 命令是可以带参数的&#xff0c;也可以不带参…...

Java:SpringBoot给Controller添加统一路由前缀

网上的文章五花八门&#xff0c;不写SpringBoot的版本号&#xff0c;导致代码拿来主义不好使了。 本文采用的版本 SpringBoot 2.7.7 Java 1.8目录1、默认访问路径2、整个项目增加路由前缀3、通过注解方式增加路由前缀4、按照目录结构添加前缀参考文章1、默认访问路径 packag…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...