RPC 框架之Thrift入门(一)
📋 个人简介
- 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
- 📝 个人主页:馆主阿牛🔥
- 🎉 支持我:点赞👍+收藏⭐️+留言📝
- 💬格言:迄今所有人生都大写着失败,但不妨碍我继续向前!🔥

目录
- 📋 个人简介
- 前言
- Thrift简介
- IDL介绍
- IDL语法学习
- 1.基本类型
- 2.struct结构体
- 3.container容器
- 4.service服务
- 5.枚举(enum)
- 6.异常(exception)
- 7.命名空间
- Thrift 编译器安装
- 入门案例
- 业务逻辑
- 服务端
- 客户端
- pom.xml
- 运行
- 结语
前言
随着近些年微服务的盛行,使得服务逐渐模块化,功能化,单个服务仅仅实现某个特定的功能或者模块,因此服务间的调用变得常见且频繁,所以高性能且快速响应的服务调用成了必须去面对的问题,传统的http请求能面对跨语言的问题,但是性能远远无法达到高并发的要求,因此更偏向底层的RPC框架越来越受到青睐,像阿里的Dubbo,谷歌的gRPC,facebook的Thrift等等!本节将学习Thrift这个跨语言的Thrift RPC框架!
Thrift简介
Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, C#, JavaScript, Node.js等都支持。(博主也是一名多语言爱好者,因此对Thrift也比较感兴趣,所以在后面,我也会写java,python 的这两种语言的RPC调用。)
IDL介绍
Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,没错,这种语言就是IDL(Interface Description Language)。
IDL 是一种用于定义接口和数据结构的语言,用于描述 Thrift 的服务接口和数据类型。在 Thrift 中使用的是 Thrift 自定义的 IDL 语言,它具有类似于其他接口描述语言的特性。
因此我们需要写IDL,然后使用Thrift编译器将IDL转换为对应的语言,我们开发者只需要实现具体的业务逻辑,无需关注底层逻辑!
IDL语法学习
在学习thrift之前,我们需要先简单的学习一下IDL的语法,很简单,和其他语言结构差不多。
1.基本类型
| 类型 | 解释 |
|---|---|
| bool | 布尔值 |
| byte | 8位有符号整数 |
| i16 | 16位有符号整数 |
| i32 | 32位有符号整数 |
| i64 | 64位有符号整数 |
| double | 64位浮点数 |
| string | UTF-8编码的字符串 |
| binary | 二进制串 |
2.struct结构体
先看例子:
struct Person { // 定义 Person 结构体1: required string name; // 姓名,必选字段2: required i32 age; // 年龄,必选字段3: optional string sex; // 性别,可选字段
}
如上面所示,它类似C语言的结构体,对应java中的Bean,其中required修饰的他的值初始化是必传项。
3.container容器
有三种可用的容器类型:
- list
元素类型为t的有序列表,允许重复。类似于java中的ArrayList。 - set
元素类型为t的无序表,不允许重复。类似于java中的HashSet。 - map<t, t>
键类型为t,值类型为t的键值对,键不允许重复。类似于java中的HashMap。
例如:
struct Test {1: map<string, User> usermap,2: set<i32> intset,3: list<double> doublelist
}
4.service服务
服务的定义方法在语义上等同于面向对象语言中的接口。
service PersonService { // 定义 PersonService 服务接口Person getByName(1: string name); // 根据姓名获取 Person 信息bool save(1: Person person); // 保存 Person 信息
}
5.枚举(enum)
枚举的定义形式和Java的Enum定义差不多,例如:
enum Sex {MALE,FEMALE
}
6.异常(exception)
thrift支持自定义exception,规则和struct一样,如下:
exception RequestException {1: i32 code;2: string reason;
}
7.命名空间
thrift的命名空间相当于Java中的package的意思,主要目的是组织代码。thrift使用关键字namespace定义命名空间,例如:
namespace java com.aniu.service
namespace py example
namespace 后跟的是你要转化的语言以及生成的文件所在的包!
Thrift 编译器安装
写完IDL文件后,我们需要将其转换成对应语言!因此,我们需要先安装Thrift编译器!这里博主用的Windows,macos和Linux自行下载!
网址:https://dlcdn.apache.org/thrift/0.19.0/thrift-0.19.0.exe
下载安装完成后,配置完环境变量,如下图,可查看版本!后序在其他语言例如java中引入maven包时,需要对应版本!

入门案例
这里编写一个简单的入门案例,实现rpc远程过程调用!
定义thrift 文件 person.thrift
namespace java com.aniu.servicestruct Person { // 定义 Person 结构体1: required string name; // 姓名,必选字段2: required i32 age; // 年龄,必选字段3: optional string sex; // 性别,可选字段
}service PersonService { // 定义 PersonService 服务接口Person getByName(1: string name); // 根据姓名获取 Person 信息bool save(1: Person person); // 保存 Person 信息
}
使用
thrift --gen java user.thrift
命令,即可在当前目录下生成gen-java目录,里面即是生成的java代码!


引入对应版本的Maven包
<dependency><groupId>org.apache.thrift</groupId><artifactId>libthrift</artifactId><version>0.19.0</version></dependency>
目录结构如下:

如上图,Person和PersonService即为thrift编译器将IDL转换后生成的java代码。
业务逻辑
PersonService里面有两个接口,我们需要实现接口,在实现类里面写业务逻辑。

package com.aniu.service.impl;import com.aniu.service.Person;
import com.aniu.service.PersonService;
import org.apache.thrift.TException;public class PersonServiceImpl implements PersonService.Iface {@Overridepublic Person getByName(String name) throws TException {return new Person(name,18);}@Overridepublic boolean save(Person person) throws TException {return false;}
}
服务端
package com.aniu.server;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import com.aniu.service.PersonService;
import com.aniu.service.impl.PersonServiceImpl;
public class Server {public static void main(String[] args) {try{// 创建一个新的 Thrift 服务端套接字,监听在端口 9000 上TServerSocket socket = new TServerSocket(9000);// 创建一个 PersonService 的 Processor。Processor 是 Thrift 中用于处理请求的接口,它需要一个实现了 PersonService 接口的对象作为参数。PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl());// 创建一个二进制协议工厂对象。Thrift 支持多种协议,如 TBinaryProtocol、TCompactProtocol、TJSONProtocol 等,这里选择的是二进制协议。TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();// 创建一个 TSimpleServer 的参数对象 args1,并将之前创建的套接字、Processor 和协议工厂设置为其属性。TServer.Args args1 = new TSimpleServer.Args(socket);args1.processor(processor);args1.protocolFactory(factory);// 使用之前设置好的参数创建 TSimpleServer 对象TSimpleServer tSimpleServer = new TSimpleServer(args1);// 开始执行 TSimpleServer,开始监听并处理客户端的请求。tSimpleServer.serve();}catch (Exception e){System.out.println(e);}}
}
客户端
import com.aniu.service.PersonService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
public class Client {public static void main(String[] args) {try{// 创建一个 Thrift 的套接字对象,连接到在本地主机(localhost)的9000端口上运行的 Thrift 服务。TSocket socket = new TSocket("localhost", 9000);// 创建一个使用二进制协议的实例,该协议用于在客户端和服务器之间传输数据。TBinaryProtocol protocol = new TBinaryProtocol(socket);// 创建一个Thrift 客户端实例,它使用前面创建的二进制协议实例进行通信。PersonService.Client client = new PersonService.Client(protocol);// 打开与服务器端的连接,通过客户端对象(client)进行远程过程调用(RPC)或其他通信操作socket.open();// RPC 调用Person person = client.getByName("aniu");System.out.println(person);}catch (Exception e){System.out.println(e);}}
}
pom.xml
<dependencies><dependency><groupId>org.apache.thrift</groupId><artifactId>libthrift</artifactId><version>0.19.0</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.5</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version><scope>compile</scope></dependency><dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>1.3.5</version><scope>compile</scope></dependency></dependencies>
运行
先启动服务端,再启动客户端,即可实现RPC调用!

结语
本节实现了一个简单的案例,但对于thrift的服务端如何创建的,客户端如何调用没有具体讲解,基本都在注释里,下一篇博文来讲解原理以及实现跨语言RPC调用!
相关文章:
RPC 框架之Thrift入门(一)
📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜📝 个人主页:馆主阿牛🔥🎉 支持我:点赞👍收藏⭐️留言Ὅ…...
【C++】运算符重载 ⑥ ( 一元运算符重载 | 后置运算符重载 | 前置运算符重载 与 后置运算符重载 的区别 | 后置运算符重载添加 int 占位参数 )
文章目录 一、后置运算符重载1、前置运算符重载 与 后置运算符重载 的区别2、后置运算符重载添加 int 占位参数 上 2 2 2 篇博客 【C】运算符重载 ④ ( 一元运算符重载 | 使用 全局函数 实现 前置 自增运算符重载 | 使用 全局函数 实现 前置 - - 自减运算符重载 )【C】运算符…...
538. 把二叉搜索树转换为累加树
题目描述 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下,二叉搜索树满足下列约束…...
java8日期时间工具类
【README】 1)本文总结了java8中日期时间常用工具方法;包括: 日期时间对象格式化为字符串;日期时间字符串解析为日期时间对象;日期时间对象转换; 转换过程中,需要注意的是: Instan…...
算法-动态规划/trie树-单词拆分
算法-动态规划/trie树-单词拆分 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/word-break/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 动态规划 2.1 解题思路 dp[i]表示[0, i)字符串可否构建那么dp[i]可构建的条件是&…...
React框架核心原理
一、整体架构 三大核心库与对应的组件 history -> react-router -> react-router-dom react-router 可视为react-router-dom 的核心,里面封装了<Router>,<Route>,<Switch>等核心组件,实现了从路由的改变到组件的更新…...
python-pytorch 利用pytorch对堆叠自编码器进行训练和验证
利用pytorch对堆叠自编码器进行训练和验证 一、数据生成二、定义自编码器模型三、训练函数四、训练堆叠自编码器五、将已训练的自编码器级联六、微调整个堆叠自编码器 一、数据生成 随机生成一些数据来模拟训练和验证数据集: import torch# 随机生成数据 n_sample…...
制作 3 档可调灯程序编写
PWM 0~255 可以将数据映射到0 75 150 225 尽可能均匀电压间隔...
源码分享-M3U8数据流ts的AES-128解密并合并---GoLang实现
之前使用C语言实现了一次,见M3U8数据流ts的AES-128解密并合并。 学习了Go语言后,又用Go重新实现了一遍。源码如下,无第三方库依赖。 package mainimport ("crypto/aes""crypto/cipher""encoding/binary"&quo…...
CSDN Q: “这段代码算是在STC89C52RC51单片机上完成PWM呼吸灯了吗?“
这是 CSDN上的一个问题 这段代码算是在STC89C52RC51单片机上完成PWM呼吸灯了吗,还是说得用上定时器和中断函数#include <regx52.h> 我个人认为: 效果上来说, 是的! 码以 以Time / 100-Time 调 Duty, 而 for i loop成 Period, 加上延时, 实现了 PWM周期, 虽然…...
Linux系统编程系列之线程池
Linux系统编程系列(16篇管饱,吃货都投降了!) 1、Linux系统编程系列之进程基础 2、Linux系统编程系列之进程间通信(IPC)-信号 3、Linux系统编程系列之进程间通信(IPC)-管道 4、Linux系统编程系列之进程间通信-IPC对象 5、Linux系统…...
Linux CentOS7 vim多文件与多窗口操作
窗口是可视化的分割区域。Windows中窗口的概念与linux中基本相同。连接xshell就是在Windows中新建一个窗口。而vim打开一个文件默认创建一个窗口。同时,Vim打开一个文件也就会建立一个缓冲区,打开多个文件就会创建多个缓冲区。 本文讨论vim中打开多个文…...
SPI 通信协议
1. SPI通信 1. 什么是SPI通信协议 2. SPI的通信过程 在一开始会先把发送缓冲器的数据(8位)。一次性放到移位寄存器里。 移位寄存器会一位一位发送出去。但是要先放到锁存器里。然后从机来读取。从机的过程也一样。当移位寄存器的数据全部发送完。其实…...
【图像处理】使用各向异性滤波器和分割图像处理从MRI图像检测脑肿瘤(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
5个适合初学者的初级网络安全工作,网络安全就业必看
前言 网络安全涉及保护计算机系统、网络和数据免受未经授权的访问、破坏和盗窃 - 防止数字活动和数据访问的中断 - 同时也保护用户的资产和隐私。鉴于公共事业、医疗保健、金融以及联邦政府等行业的网络犯罪攻击不断升级,对网络专业人员的需求很高,这并…...
Kafka核心原理
1、Topic的分片和副本机制 分片作用: 解决单台节点容量有限的问题,节点多,效率提升,吞吐量提升。通过分片,将一个大的容器分解为多个小的容器,分布在不同的节点上,从而实现分布式存储。 分片…...
探秘前后端开发世界:猫头虎带你穿梭编程的繁忙街区,解锁全栈之路
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...
洛谷_分支循环
p2433 问题 5 甲列火车长 260 米,每秒行 12 米;乙列火车长220 米,每秒行 20 米,两车相向而行,从两车车头相遇时开始计时,多长时间后两车车尾相离?已知答案是整数。 计算方式:两车车…...
MySQL数据库入门到精通——进阶篇(3)
黑马程序员 MySQL数据库入门到精通——进阶篇(3) 1. 锁1.1 锁-介绍1.2 锁-全局锁1.3 锁-表级锁1.3.1 表级锁-表锁1.3.2 表级锁元数据锁( meta data lock,MDL)1.3.3 表级锁-意向锁1.3.4 表级锁意向锁测试 1.4 锁-行级锁1.4.1 行级锁-行锁1.4.2…...
Mind Map:大语言模型中的知识图谱提示激发思维图10.1+10.2
知识图谱提示激发思维图 摘要介绍相关工作方法第一步:证据图挖掘第二步:证据图聚合第三步:LLM Mind Map推理 实验实验设置医学问答长对话问题使用KG的部分知识生成深入分析 总结 摘要 LLM通常在吸收新知识的能力、generation of hallucinati…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
