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…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...