Thrift应用实践—基本篇

Thrift 分布式通信深度解析:架构设计、实现原理与实战应用 Thrift以其高效的序列化框架、跨语言支持和简单的接口定义语言等特点,在分布式系统中得到了广泛应用。通过深入了解Thrift的架构设计、实现原理和实战应用,开发人员可以更好地利用这一框架构建高效、稳定、可扩展的分布式系统。此外,Thrift还提供了丰富的错误处理策略和安全传输协议,进一步提高了系统的稳定性和安全性。在实际应用中,开发人员需要根据具体需求选择合适的传输层实现和协议类型,以确保数据传输的高效性和安全性。 阅读详情

1.简介

    Thrift作为一个RPC框架,很好的解决了跨语言调用问题,并提供灵活高效的传输方式和Server模式。在实际应用中,个人认为Thrift更多的是用于系统的解耦,负责模块间的通信,使各模块可以独立开发、测试和发布等,一般情况下无需担心跨语言调用和传输性能问题;而对外调用还是偏向于更具通用性的HTTP REST。在本帖中,我们通过编写一个基本实例来了解Thrift的远程调用。

2.准备工作

    首先使用Manven创建一个Java Project,并加入Thrift依赖

<dependencies>
    <dependency>
       <groupId>org.apache.thrift</groupId>
       <artifactId>libthrift</artifactId>
       <version>0.9.3</version>
    </dependency>
    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
       <version>1.7.12</version>
    </dependency>
</dependencies>

3.编写Thrift文件

    Thrift为我们提供了 IDL(Interface Definition Language) 来编写通用的服务接口文件(后缀为thrift的文件),并编译生成对应语言的模板代码,从而解决跨语言调用问题。比如我们使用的是Java,则生成java文件,使用的是Node,那就生成js文件。

    假如我们向一个影院信息系统查询一部电影的数据,那我们需要一个获取影片信息的接口,客户端传入查询影片的名称,服务端处理后返回该影片的详细数据。

    首先我们需要一个电影实体,用于装载相关的数据,代码如下所示。
MovieModel.thrift

//定义java命名空间,对应package的值
namespace java com.thrift.simple.model  

struct Movie { 
  1:string chName //中文名
  2:string enName //英文名
  3:string type //类型
  4:string digital //数字种类
  5:i64 releaseDate //上映日期
  6:i32 duration //时长
  7:i32 price //售价
  8:map<string, bool> screenings //场次信息,是否有票
} 

    上述代码涉及到 IDL 支持的数据类型,有兴趣的读者可以到 http://thrift.apache.org/docs/types 简单学习一下,我们这里没有添加 required 或 optional 声明,Thrift 默认视为 required 处理,两者的区别是 required 声明的类型一定会序列化,如果你没有给它赋值,生成的 java 代码也会设置一个默认值,optional 未赋值则不会序列化。此外 IDL 只支持 java 的基本类型,像 Date 等类型是不支持的,需在代码中转换。

    接下来需要一个查询电影信息的服务接口,代码如下所示。
MovieOperator.thrift

namespace java com.thrift.simple.service
//引用另一个Thrift文件,并通过“文件名.数据类型”的形式调用。
include "MovieModel.thrift" 

service MovieOperator { 
  MovieModel.Movie getMovie(1:string chName)
} 

    这样我们需要的Thrift文件就准备好了,输入如下命令即可生成对应的java文件。

//加上-r选项,同时生成include文件
thrift -r --gen java MovieOperator.thrift

    将生成的java文件放入工程对应的package下,就可以开始使用了,先简单分析一下生成的Movie和MovieOperator类。

Movie类
    图3-1是Movie类的部分method,可以看到除了本身用于传输的read和write方法外,set和get,Object的equals和hashcode甚至compareTo方法都帮你写好了,在本例中我们可以直接作为Movie实体使用。

图1-1
图3-1

MovieOperator类
    这个类的代码看上去很多,但结构简单,主要成员如图3-2所示。其中Iface是我们刚刚定义的接口,Client和Processor分别用于客户端和服务端,里面封装着远程调用的请求和接收方法,调用过程中会用到getMovie_args和getMovie_result方法来分别获取参数和返回值。最后3个Async方法用于异步处理,本例不作详细介绍。

这里写图片描述
图3-2

4.客户端实现

    现在正式编写代码,首先创建客户端的ThriftClient类,代码如下所示。

public class ThriftClient {
    public static void main(String[] args) {
        //对java的socket进行封装,定义传输的基本方法
        TTransport baseTrans = new TSocket("localhost", 6060, 2000);
        //进一步封装,使用按帧传输的方式,服务端必须使用非阻塞类型
        TTransport frameTrans = new TFramedTransport(baseTrans); 
        //采用二进制协议,服务端协议须保持一致
        TProtocol protocol = new TBinaryProtocol(frameTrans); 
        //将配置传入Client对象
        MovieOperator.Client client = new MovieOperator.Client(protocol);

        try {
            //TSocket初始化并创建Socket连接
            frameTrans.open();
            //远程调用getMovie方法并获取返回值
            Movie movie = client.getMovie("谍影重重5");
            System.out.println("get remote info ----> " + movie.toString());
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            //别忘了关闭连接
            frameTrans.close();
        }
    }
}

5.接口服务实现

    编写Iface接口的实现类,也就是客户端来找服务端干的具体事情,代码如下所示。

public class MovieOperatorImpl implements MovieOperator.Iface {
    @Override
    public Movie getMovie(String chName) throws TException {
        //创建实体对象
        Movie movie = new Movie();
        //本例就不从数据库中获取了,直接塞入一份测试数据
        movie.setEnName("Jason Bourne");
        movie.setChName(chName);
        movie.setPrice(49);
        movie.setDigital("原版3D");
        movie.setDuration(123);
        movie.setReleaseDate(dateTrans("2016-08-23"));
        movie.setType("英语");
        Map<String, Boolean> map = new HashMap<String, Boolean>();
        map.put("18:15", false);
        map.put("22:30", true);
        movie.setScreenings(map);

        return movie;
    }

    private long dateTrans(String date) {
        long defaultTime = 0;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            defaultTime = format.parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return defaultTime;
    }
}

6.服务端实现

    最后编写服务端ThriftServer类,代码如下所示。

public class ThriftServer {
    public static final int servePort = 6060;

    public static void main(String[] args) {
        MovieOperator.Iface operator = new MovieOperatorImpl();
        //将实现类的对象放入processor中维护,在客户端请求时,会映射到具体的执行方法
        TProcessor processor = new MovieOperator.Processor<>(operator);

        try {
            //创建非阻塞的传输对象,对ServerSocket进行了封装
            TNonblockingServerTransport nioSocket = new TNonblockingServerSocket(servePort);
            TNonblockingServer.Args nonBlockingArgs = new TNonblockingServer.Args(nioSocket);
            //放入process并设置transport和protocol的类型,注意与客户端对应
            nonBlockingArgs.processor(processor);
            nonBlockingArgs.transportFactory(new TFramedTransport.Factory());
            nonBlockingArgs.protocolFactory(new TBinaryProtocol.Factory());
            //实例化Server对象
            TServer server = new TNonblockingServer(nonBlockingArgs);
            System.out.println("service start at " + servePort);
            //启动并监听
            server.serve();
        } catch (TException e) {
            e.printStackTrace();
        }
    }
}

    上述代码唯一存在疑惑的地方,就是TNonblockingServer的内部类Args,为什么不直接对TNonblockingServer实例化,而是借助该类配置所需的参数呢?

    我们来看图6-1,TNonblockingServer只提供了一个以AbstractNonblockingServerArgs为参数的构造函数,因此必须先创建它的静态内部类Args对象。

这里写图片描述
图6-1

    我们继续查看Args的继承结构,如图6-2所示。

这里写图片描述
图6-2

    跟踪父类到TServer中,发现AbstractServerArgs中定义了Server所需的基本数据:Transport、Process和Protocol,也就是刚刚配置的参数属性,如图6-3所示。

这里写图片描述
图6-3

    看到这里,我们已经明白大体的设计方式了,TServer作为所有Server类型的父类,除了定义基础属性和操作标准外,还提供了一个抽象的Args类用于参数的配置和管理,子类根据需要继承并扩展该类即可,如经常使用的TThreadPoolServer就是这样干的。因此在实例化其他Server时,只需创建并配置对应的Args对象即可,体现了代码的封装性和扩展性。

    到此代码就完成了,我们看下运行的结果,运行结果如下。

get remote info ----> Movie(chName:谍影重重5, enName:Jason Bourne, type:英语, digital:原版3D, releaseDate:1471881600000, duration:123, price:49, screenings:{18:15=false, 22:30=true})

Process finished with exit code 0

7.小结

    最后再回顾一下,首先我们使用Thrift提供的IDL编写了两个Thrift文件,一个是Movie实体,另一个是MovieOperator提供服务接口,通过命令生成java代码。客户端指定好传输方式和传输协议后,调用MovieOperator的Client与服务端交互。服务端这边先实现了MovieOperator的Iface接口,编写好具体的实现代码MovieOperatorImpl,接着把MovieOperatorImpl放入MovieOperator Processor中管理,然后指定与客户端对应的Server类型、传输方式和传输协议并实例化Server对象,最后启动服务并监听指定端口。

    本例源码下载 http://download.youkuaiyun.com/detail/roderick2015/9613104


Tips:
    如果把Thrift生成的代码放入工程后,出现如下图所示的问题,说明你的JDK编译版本太低,在1.5中的确不能这样使用。

这里写图片描述

    可以参照下面的两张图,改成高一点的版本就行啦。

这里写图片描述

这里写图片描述

后端领域中 Thrift 的优势与实践 本文旨在全面剖析Apache Thrift框架在后端开发中的技术优势和实践经验。内容涵盖Thrift的核心架构、协议设计、跨语言支持机制,以及在实际项目中的应用场景和性能优化策略。通过本文,读者将掌握如何利用Thrift构建高效、可靠的分布式服务系统。文章首先介绍Thrift的基本概念和核心组件,然后深入分析其协议和传输层实现。接着通过代码示例展示具体使用方法,并讨论性能优化策略。最后探讨Thrift在现代架构中的应用场景和发展趋势。: 远程过程调用,使程序能够像调用本地方法一样调用远程服务。 阅读详情

相关推荐

thrift介绍与简单应用

thrift介绍与简单应用1 为什么要使用thrift1.1 应用场景在哪儿1.2 其他方案比较1.3 不支持什么:2 thrift 基本概念2.1 层级3 简单应用3.1 idl3.2 生成接口3.3 实现服务3.4 实现调用4 比较swift(*) 1 为什么要使用thrift 1.1 应用场景在哪儿 1.2 其他方案比较 1.3 不支持什么: 不能返回null 不支持继承,多态 2 th...

taoxin52的专栏 1407

实践常见的RPC框架:Thrift

实践常见的RPC框架:Thrift 文章目录实践常见的RPC框架:Thrift一、Thrift介绍二、Thrift使用示例2.1 安装Thrift编译器2.2 编写Thrift的IDL文件2.3 通过Thrift实现RPC功能(1) demo-thrift-api(2) demo-thrift-server 服务端代码(3) demo-thrift-client 客户端代码 一、Thrift介绍 维基百科上对Thrift的介绍如下: Thrift是一种接口描述语言和二进制通讯协议,[1]它被用来定义和创

hefrankeleyn的博客 1201

Thrift简介及实例应用

最近Boss让我研究一下Thrift,所以通过查阅大量的资料,整理出以下文档,在此备份。 一、引言 1、 背景 Thrift源于facebook,2007年facebook提交Apache基金会将Thrift作为一个开源项目。Facebook创造Thrift的目的是为了解决facebook系统中各系统间大数据量的传输通信以及系统间语言环境不同需要跨平台的问题。 2、 简介 Apache

Eliot 6751

Thrift的编译

#Java项目中使用thrift: 第一次学习java thrift的时候,我们都是手动运行thrift编译器,然后把生成的java文件复制进自己的项目中使用。 但是这种方式在大型项目中不可取。 一是因为thrift编译器的执行操作应该放在公共的机器上而不是每一个开发者在本地运行,本地运行可能导致很多不一致问题,如版本等。 二是从开发角度来说,thrift文件本质定义的是一个接口,接口的实现方和使...

西京刀客 7913

《SparkSQL内核剖析》【Thrift Server篇】

前两天,我司开发环境Zeppelin在跑一个统计任务时,挂了,报错信息如下: TODO: 此处应有截图 我推测是Thrift Server内存不足,导致通信失败了,具体原因没有深究。然而,Thrift这个看似熟悉却又陌生的词汇吸引了我的注意力。碰巧今天在学习《Spark内核剖析》第10章,Spark SQL连接Hive时,又一次提到了Thrift,于是便有了此文。 什么是Thrift Thrift...

renq的专栏 1278

Thrift.exe在Windows环境下的实践指南

Apache Thrift是由Facebook开源的一个高效的跨语言服务开发框架,它结合了代码生成引擎和运行时库来构建可扩展的跨语言服务。Thrift旨在简化网络服务编程,支持包括C++, Java, Python等多种编程语言。它的出现大大降低了不同编程语言环境间的数据交换和分布式服务调用的复杂性。Thrift的核心是一个接口定义语言(IDL),通过IDL文件定义数据类型和服务接口,然后使用Thrift编译器工具(thrift.exe)针对不同的编程语言生成源代码。

weixin_42588672的博客 1175

大数据全栈式运维开发

本次课程让学员全面系统地学习大数据平台运维,开发的操作。课程内容涉及到大数据生态系统的各项工具,内容全面,讲解细致,助您全面掌握大数据平台运维及开发工具的作用

thrift介绍与实践

NULL 博文链接:https://leign.iteye.com/blog/1055627

07-Thrift高级

Thrift高级在之前的案例中,使用的都是TCP服务,但是在实际网络中,TCP端口要求很严,我们不可能为每个微服务都提供一个端口,这也是近几年HTTP越来越占主流的一个很重要原因。这里,我们研究一下 Thrift Over HTTP。 依赖与感谢版本必须为最新0.10.0,这个版本提供了THttpServer和THttpClient这两个核心类。 这里要感谢QQ群【thrift技术交流群】里的l

笨笨D幸福 - 后花园 777

windows下vs2010编译的thrift,包含lib和cpp源码

windows下vs2010完美编译thrift,包含lib文件和src源码,thrift版本为thrift-0.11.0

thrift 教程

thrift 教程,有文档和demo工程,demo中包含了thrift的连接池和连接重试机制,同时也有thrift的几种不同的IO模式的例子

[thrift] thrift基本原理及使用

Thrift架构 thrift主要用于各个服务之间的RPC通信,支持跨语言。thrift是一个典型的CS结构,客户端和服务端可以使用不同的语言开发,thrift通过IDL(Interface Description Language)来关联客户端和服务端。thrift的整体架构图如下图所示 如下图所示为thrift的网络栈结构 thirft使用socket进行数据传输,数据以特定的格...

zkp_java的专栏 7万+

Thrift使用示例代码

Thrift使用示例代码,主要配合博客《由浅入深了解thrift》写的测试代码

简述thrift与应用分析

前言     本篇将以thrift-0.9.0为背景讲述thrift的基础,使用案例,启发。 概述   thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa,JavaScript, Node.js, Sma

chlaws的专栏 1万+

thrift的使用介绍

NULL 博文链接:https://gemantic.iteye.com/blog/1199214

多智能体强化学习论文——SEAC(NIPS 2020)

存在的问题&研究动机&研究思路 在稀疏奖励的环境下,多智能体的exploration存在效率不足等问题。 在IAC的基础上尝试加入重要性采样,使得每次更新智能体iii的参数时,不再仅仅使用智能体iii的数据,而是使用所有智能体的数据进行智能体iii数据的更新。 对于原始的IAC算法是on-policy的,而SEAC则是off-poligy的。 创新点 在每个智能体iii的actoriactor_iactori​和criticicritic_icritici​的更新过程中,都加入了重要性

我的AI笔记 1206

thrift IDL基本语法

thrift简介 Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smal...

blade1080的博客 3008

基于STM32L4XX的环境光传感器(LTR-303ALS-01)应用程序设计

/ 状态寄存器的位[2:0]表示数据状态,例如位2为1表示新数据就绪[citation:6]#define LTR303_REG_DATA_CH0_LOW 0x8D // CH0数据低字节。#define LTR303_REG_DATA_CH0_HIGH 0x8E // CH0数据高字节。#define LTR303_REG_DATA_CH1_LOW 0x8F // CH1数据低字节。#define LTR303_REG_DATA_CH1_HIGH 0x90 // CH1数据高字节。

myron6688的博客 404

thrift介绍及应用(一)—介绍

一、概述         Thrift是Apache下的一个子项目,最早是Facebook的项目,后来Facebook提供给Apache作为开源项目,在官网上,Thrift被描述为“Scalable Cross-Language Services Implementation”,说的通俗一些,Thrift具有以下特征: 它有自己的跨机器的通信框架,并提供一套库。它是一个代码生成器,按照它的

guxch的专栏 2万+

AIGC游戏开发:如何评估生成内容的玩家满意度?

如何量化评估生成内容对玩家体验的影响?本文聚焦AIGC生成的游戏内容(包括但不限于剧情、关卡、NPC对话、道具),系统探讨玩家满意度的评估方法论,覆盖主观与客观评估、静态与动态内容、短期与长期体验等场景。核心概念:定义AIGC与玩家满意度的关联维度;评估方法:主观(问卷/访谈)与客观(行为/生理数据)评估的技术细节;数学模型:构建多指标融合的评估模型;实战案例:以AIGC生成关卡为例,演示从数据采集到模型落地的全流程;工具资源:推荐数据采集、分析与建模的工具链;

AI天才研究院 1223

挣脱枷锁:网页禁止复制/F12失效/右键失灵时的破局之道

大家在网上冲浪的否遇到过这种情况?急需网页上的一段关键信息、一段优美的文字、一个重要的代码片段,或者只是想收藏某篇文章,却发现:文本选择被阻止,右键菜单被禁用,开发者工具(F12)被屏蔽,查看源代码(Ctrl+U)失效?本文会有力解决这些封锁。

安德洛夫 2109

Thrift IDL基本语法

文章目录thrift原理IDL基本类型object类型struct 结构体Container (容器)enum (枚举)常量类型ExceptionService (服务定义类型)Namespace (名字空间)Comment (注释) thrift原理 https://www.jianshu.com/p/f12a442d510c IDL Thrift 采用IDL(Interface Definition Language)来定义通用的服务接口,然后通过Thrift提供的编译器,可以将服务接口编译成不同语言编

weixin_38370441的博客 1230

三峡大学-微机原理与接口技术实验

其中,A15接E1,因此,A15为1,A14A13A12A11A10A9A8A7通过八输入与非门74LS30与E2连接,因此A14A13A12A11A10A9A8A7为11111111,A6A5A4与CBA连接,因此A6A5A4为101,A3A2A1A0不参与译码,因此IO5的地址范围为1111 1111 1101 0000B~1111 1111 1101 1111B,即0FFD0H~0FFDFH。如图1所示,若IO0输出为低电平,则需要E1接高电平,E2接低电平,E3接低电平,CBA的输入为000。

m0_62222486的博客 495
下一篇: 消息队列的流派之争
Roderick2015
博客等级 码龄10年 9粉丝 8原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值