百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

一文带你了解Thrift,一个可伸缩的跨语言RPC框架

ccwgpt 2024-10-15 08:57 32 浏览 0 评论

Thrift 是什么

研究分布式调用链工具pinpoint的时候,在源码里看到了Thrift相关的代码,所以来了兴趣,想研究研究这个框架。

Thrift 目前是 Apache 的一个项目,但是它是由facebook研发产生的。

它的定位是一个 跨语言的RPC服务开发框架。

在个不同语言环境的系统中承担大量数据传输和通信的工作。

Thrift 支持包括上图中所有等28种语言,所以使得在使用不同编程语言的程序,可以很容易的传输共享数据和进行远程过程调用。

它是一个轻量级的,独立于语言的开发框架,在点对点rpc数据传输,数据的序列化上为我们提供了比较简洁的抽象和实现。

同样的,由于Thrift在传输数据时,采用的是二进制,相对于在HTTP协议中使用的xml和json占用体积更小,在很多高并发、数据量级大的系统中更加有优势。

我们通过定义一个以.thrift结尾的文件作为输入源,内容包含接口的定义,然后通过生成代码的方式,来构建不同语言的RPC客户端和服务端。

Thrift 的各个组件层级

在 Thrift 的客户端和服务端交互中,各个组件都是比较灵活的,做到了充分的低耦合,所以我们可以基于不同的应用场景,选择不同的方式搭建或是语言实现。

由上图,可以看出,最上层是我们编写的Thrift代码,它是一种IDL(接口描述语言), 是用于描述的服务接口信息的。 我们在这个文件中写好相关的注释,就可以用它来作为接口文档,提供给客户端使用了。 同时,IDL文件,也是自动生成接口代码的输入源,定义出来的接口能够很灵活的支持扩展。

第二层是使用Thrift编译工具生成的代码,主要用于结构化的数据解析,发送和接收

通信协议层主要是定义数据传输的格式,对传输的数据进行序列化和反序列化, 从协议划分上来说,主要包含两个方面,一是文本,而是二进制,既然使用了Thrift,使用其二进制协议占多数,当然更是要结合实际的业务场景来分析考虑。

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

Thrift 的数据结构

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

图片来自 wangyangfu,其中,byte、i16、i32、i64分别表示:8/16/32/64位有符号整数。

Thrift 和 Http 区别?

其实 Thrift 的主要特点就是跨语言、能自动生成客户端。相对于 http 协议而言,算是比较小众。 它是基于 socket,通过 TCP 协议实现,相比较无连接、无状态的 HTTP 协议的,每次打开、关闭连接会比较消耗性能 并且需要管理维护很多 IDL 文件。

基于thrift实现高效的二进制传输 而 http 大部分是通过 json 来实现的,字节大小和序列化耗时都比 Thrift 要更消耗性能。

总的来说,Thrift 更常见用于公司内部的系统服务之间调用,性能消耗比较低,保证服务质量,提高传输效率,而 http 主要用于对外的接口调用,浏览器、移动端、第三方接口等。

Thrift 的安装使用

Thrift的官网地址是:

http://thrift.apache.org

这里我使用的版本是 thrift-0.10.0.exe,下载地址:

http://archive.apache.org/dist/thrift/0.10.0/thrift-0.10.0.exe

将下载好的trift-0.10.0.exe 重命名为 thrift.exe 并且在控制面板--> Path环境变量中配置exe所在的目录 配置好后,命令行执行:

thrift -version 应该会显示

表明安装成功。

Thrift 的编译

新建一个 maven 工程,在intf目录下新建一个 IUserInfo.thrift 文件,内容为:

 struct User{
    1: i32 id
    2: string name
}

service UserService{
    User getUser(1:i32 uid)
}

cmd命令行进入这个文件所在目录,执行如下命令:

 thrift -gen java IUserInfo.thrift

语法格式为: thrift --gen

使用双面面命令即可将IDL文件编译成对应语言的接口文件。

执行完后,会生成两个Java类。当然idea开发工具也提供了Thrift的编译器支持,在插件仓库中搜索安装,配置相关的参数后,也能完成编译。

编写 Thrift 服务端

    // 业务处理器
        TProcessor processorr = new UserService.Processor<UserService.Iface>(new UserServiceImpl());
        // 设置服务器
        TServerSocket serverSocket = new TServerSocket(9999);
        // 传输协议为二进制
        TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();
        // 使用单线程阻塞 I/O 模型
        TServer.Args simpleArgs = new TServer.Args(serverSocket).processor(processorr).protocolFactory(protocolFactory);
        TServer server = new TSimpleServer(simpleArgs);
        System.out.println("开启侠梦的Thrift服务器,监听端口:9999");
        server.serve();

编写 Thrift 客户端

           // 设置调用的服务地址-端口
        TTransport tTransport = new TSocket("localhost", 9999);
        // 使用二进制协议
        TProtocol protocol = new TBinaryProtocol(tTransport);
        // 使用的接口
        UserService.Client client = new UserService.Client(protocol);
        // 打开 Socket
        tTransport.open();
        System.out.println(client.getUser(1));
        tTransport.close();

依次执行Server 端 和Client 后,效果如下:

至此,我们就完成了第一个Thrift 程序的编写。

pinpoint 中 为什么采用 Thrift 呢?

通过使用二进制格式(thrift)可以提高编码速度,虽然它使用和调试要难一些。也有利于减少网络使用,因为生成的数据比较小。

如果将一个长整型转换为固定长度的字符串, 数据大小一般是8个字节。然而,如果你用变长编码,数据大小可以是从1到10个字符,取决于给定数字的大小。

为了减小数据大小,pinpoint 使用 Thrift 的CompactProtocol协议(压缩协议)来编码数据,因为变长字符串和记录数据可以为编码格式做优化。pinpoint agent通过基于跟踪的根方法的时间开始来转换其他的时间来减少数据大小。

固定长度编码和可变长度编码的对比

为了得到关于三个不同方法(见上图)被调用时间的数据,不得不在6个不同的点上测量时间,用固定长度编码这需要48个字节(6 * 8)。

以此同时,pinpoint agent 使用可变长度编码并根据对应的格式记录数据。然后在其他时间点通过和参考点比较来计算时间值(在vector中),根方法的起点被确认为参考点。这只需要占用少量的字节,因为vector使用小数字。图4中消耗了13个字节。

如果执行方法花费了更多时间,即使使用可变长度编码也会增加字节数量。但是,依然比固定长度编码更有效率。

总结

先总结一下介绍的内容:

  • 介绍了Thrift 的基本概念。
  • Thrift 的协议层的作用
  • Thrift 的数据结构
  • Thrift 和 Http 区别?
  • Thrift 的安装使用
  • Thrift 的入门例子编写。
  • Thrift 的编译和运行
  • pinpoint什么采用 Thrift 的原因?

本篇文章介绍了 跨语言的RPC框架 Thrift的入门知识,起源于研究Pinpoint的源码,在这里想说的是: 研究阅读某个框架的源码其实是很耗费精力的一件事,因为不同的人读同样的代码会有不同的感受,这取决于各自的认知和知识深度不同,但是我觉得思路应该都是一致的,那就是不应该局限在框架本身,而是站在创造者的角度,去思考,为什么最后造出了这样一个优秀的框架,它依赖的那些底层的硬件、或是软件。由点及面的将其剖析完整,希望能帮助到你。

创建了一个java方面的互助群,和其他传统的学习群不同。

本群主要致力于解决项目中的疑难问题,在遇到项目难以解决的

在本群,你可以

1)阐述你在开发过程中遇到的问题,群友集思广益,高效解答。

2)分享自己学习的一些心得,让后来学习者少踩坑。

3)资源共享,无论是好的学习视频还是文档都可以在群内共享。

别人有可能可以给你提供一些思路和看法

同样,如果你也乐于帮助别人,那解决别人遇到的问题,也同样对你是一种锻炼。

想邀你加入这个有温度的社群

分享经验和心得

集思广益,高效解答问题

帮助他人,锻炼自己

相关推荐

RACI矩阵:项目管理中的角色与责任分配利器

作者:赵小燕RACI矩阵RACI矩阵是项目管理中的一种重要工具,旨在明确团队在各个任务中的角色和职责。通过将每个角色划分为负责人、最终责任人、咨询人和知情人四种类型,RACI矩阵确保每个人都清楚自己...

在弱矩阵组织中,如何做好项目管理工作?「慕哲制图」

慕哲出品必属精品系列在弱矩阵组织中,如何做好项目管理工作?【慕哲制图】-------------------------------慕哲制图系列0:一图掌握项目、项目集、项目组合、P2、商业分析和NP...

Scrum模式:每日站会(Daily Scrum)

定义每日站会(DailyScrum)是一个Scrum团队在进行Sprint期间的日常会议。这个会议的主要目的是为了应对Sprint计划中的不断变化,确保团队能够有效应对挑战并达成Sprint目标。为...

大家都在谈论的敏捷开发&amp;Scrum,到底是什么?

敏捷开发作为一种开发模式,近年来深受研发团队欢迎,与瀑布式开发相比,敏捷开发更轻量,灵活性更高,在当下多变环境下,越来越多团队选择敏捷开发。什么是敏捷?敏捷是一种在不确定和变化的环境中,通过创造和响应...

敏捷与Scrum是什么?(scrum敏捷开发是什么)

敏捷是一种思维模式和哲学,它描述了敏捷宣言中的一系列原则。另一方面,Scrum是一个框架,规定了实现这种思维方式的角色,事件,工件和规则/指南。换句话说,敏捷是思维方式,Scrum是规定实施敏捷哲学的...

敏捷项目管理与敏捷:Scrum流程图一览

敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示,以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例:这个流程图涵盖了Scrum框架的主要阶段和活动,其中包...

一张图掌握项目生命周期模型及Scrum框架

Mockito 的最佳实践(mock方法)

记得以前面试的时候,面试官问我,平常开发过程中自己会不会测试?我回答当然会呀,自己写的代码怎么不测呢。现在想想我好像误会他的意思了,他应该是想问我关于单元测试,集成测试以及背后相关的知识,然而当时说到...

EffectiveJava-5-枚举和注解(java枚举的作用与好处)

用enum代替int常量1.int枚举:引入枚举前,一般是声明一组具名的int常量,每个常量代表一个类型成员,这种方法叫做int枚举模式。int枚举模式是类型不安全的,例如下面两组常量:性别和动物种...

Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!

Maven简介Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。Maven是一个跨平台的项目管理工具。主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。仔...

Java单元测试框架PowerMock学习(java单元测试是什么意思)

前言高德的技术大佬在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。”这句话让我感触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现...

Spring框架基础知识-第六节内容(Spring高级话题)

Spring高级话题SpringAware基本概念Spring的依赖注入的最大亮点是你所有的Bean对Spring容器的存在是没有意识的。但是在实际的项目中,你的Bean必须要意识到Spring容器...

Java单元测试浅析(JUnit+Mockito)

作者:京东物流秦彪1.什么是单元测试(1)单元测试环节:测试过程按照阶段划分分为:单元测试、集成测试、系统测试、验收测试等。相关含义如下:1)单元测试:针对计算机程序模块进行输出正确性检验工作...

揭秘Java代码背后的质检双侠:JUnit与Mockito!

你有没有发现,现在我们用的手机App、逛的网站,甚至各种智能设备,功能越来越复杂,但用起来却越来越顺畅,很少遇到那种崩溃、卡顿的闹心事儿?这背后可不是程序员一拍脑袋写完代码就完事儿了!他们需要一套严谨...

单元测试框架哪家强?Junit来帮忙!

大家好,在前面的文章中,给大家介绍了以注解和XML的方式分别实现IOC和依赖注入。并且我们定义了一个测试类,通过测试类来获取到了容器中的Bean,具体的测试类定义如下:@Testpublicvoid...

取消回复欢迎 发表评论: