`
zhb8015
  • 浏览: 399452 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Group-logo
Spring Roo杂谈
浏览量:0
社区版块
存档分类
最新评论

Thrift框架调研(转)--rpc

    博客分类:
  • java
阅读更多

简介

Thrift是一种开源的跨语言的RPC服务框架。Thrift最初由facebook公司开发的,在2007年facebook将其提交apache基金会开源了。对于当时的facebook来说创造thrift是为了解决facebook系统中各系统间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性。所以thrift可以支持多种程序语言,支持的语言如下: 

在多种不同的语言之间通信thrift可以作为二进制的高性能的通讯中间件,支持数据(对象)序列化和多种类型的RPC服务。Thrift是IDL(interface definition language)描述性语言的一个具体实现,Thrift适用于程序对程序静态的数据交换,需要先确定好他的数据结构,他是完全静态化的,当数据结构发生变化时,必须重新编辑IDL文件,代码生成,再编译载入的流程,跟其他IDL工具相比较可以视为是Thrift的弱项,Thrift适用于搭建大型数据交换及存储的通用工具,对于大型系统中的子系统间数据传输相对于JSON和xml无论在性能、传输大小上有明显的优势。

 

基础架构

如下图所示是thrift的协议栈整体的架构,thrift是一个客户端和服务器端的架构体系(c/s),在最上层是用户自行实现的业务逻辑代码。    第二层是由thrift编译器自动生成的代码,主要用于结构化数据的解析,发送和接收。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。Processor负责对客户端的请求做出响应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理。从TProtocol以下部分是thirft的传输协议和底层I/O通信。TProtocol是用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输。TTransport是与底层数据传输密切相关的传输层,负责以字节流方式接收和发送消息体,不关注是什么数据类型。底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。

协议层TProtocol:

在传输协议上总体上划分为文本(text)和二进制(binary)传输协议, 为节约带宽,提供传输效率,一般情况下使用二进制类型的传输协议为多数。

   1>TBinaryProtocol – 二进制编码格式进行数据传输。 

   2>TCompactProtocol – 高效的编码方式,使用类似于protobuffer的Variable-Length Quantity (VLQ) 编码(可以节省传输空间,使数据的传输效率更高)对数据进行压缩。 关于VLQ了解更多(http://en.wikipedia.org/wiki/Variable-length_quantity

   3>TJSONProtocol – 使用JSON的数据编码协议进行数据传输。 

   4>TSimpleJSONProtocol – 这种节约只提供JSON只写的协议,适用于通过脚本语言解析    

   5>TDebugProtocol – 在开发的过程中帮助开发人员调试用的,以文本的形式展现方便阅读。

 

传输层TTransport

    1>TSocket- 使用阻塞式I/O进行传输,也是最常见的模式。 

    2>TFramedTransport- 使用非阻塞方式,按块的大小,进行传输,类似于Java中的NIO。                

    3>TFileTransport- 顾名思义按照文件的方式进程传输,虽然这种方式不提供Java的实现,但是实现起来非常简单。 

    4>TMemoryTransport- 使用内存I/O,就好比Java中的ByteArrayOutputStream实现。 

    5>TZlibTransport- 使用执行zlib压缩,不提供Java的实现。

    6>TNonblockingTransport-使用非阻塞方式,用于构建异步客户端。



  服务端类型 :

    1>TSimpleServer -  单线程服务器端使用标准的阻塞式I/O。     

    2>TThreadPoolServer -  多线程服务器端使用标准的阻塞式I/O。 

    3>TNonblockingServer – 多线程服务器端使用非阻塞式I/O,并且实现了Java中的NIO通道。



数据类型

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

  • 基本类型:
    • bool:布尔值,true 或 false,对应 Java 的 boolean
    • byte:8 位有符号整数,对应 Java 的 byte
    • i16:16 位有符号整数,对应 Java 的 short
    • i32:32 位有符号整数,对应 Java 的 int
    • i64:64 位有符号整数,对应 Java 的 long
    • double:64 位浮点数,对应 Java 的 double
    • string:未知编码文本或二进制字符串,对应 Java 的 String
  • 结构体类型:
    • struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
  • 容器类型:
    • list:对应 Java 的 ArrayList
    • set:对应 Java 的 HashSet
    • map:对应 Java 的 HashMap
  • 异常类型:
    • exception:对应 Java 的 Exception
  • 服务类型:service:对应服务的类

安装使用

在Windows下安装前需要很多依赖包的安装,比较麻烦。下面介绍了在Linux下的源码安装,直接wget或手动下载最tar.gz安装包编译安装:

tar -xvf thrift-0.9.1.tar.gz

cd thrift-0.9.1

./configure

make 

make install

使用命令thrift -version,显示Thrift version 0.9.1 则表示安装成功。

我们使用到了java,所以通过ant方式构建thrift相关lib包,进入$THRIFT_HOME/lib/java目录下,在ant编译libthrift出现了如下问题

Buildfile: /letv/apps_install/thrift-0.9.1/lib/java/build.xml 

setup.init: 

mvn.ant.tasks.check: 

proxy: 

mvn.ant.tasks.download: 
[get] Getting: http://repo1.maven.org/maven2/org/apache/maven/maven-ant-tasks/2.1.3/maven-ant-tasks-2.1.3.jar 
[get] To: /letv/apps_install/thrift-0.9.1/lib/java/build/tools/maven-ant-tasks-2.1.3.jar 
[get] Not modified - so not downloaded 

mvn.init: 
Unable to obtain resource from /letv/apps_install/thrift-0.9.1/lib/java/build/tools/maven-ant-tasks-2.1.3.jar: java.util.zip.ZipException: error in opening zip file
[typedef] Unable to obtain resource from /letv/apps_install/thrift-0.9.1/lib/java/build/tools/maven-ant-tasks-2.1.3.jar: 
[typedef] java.util.zip.ZipException: error in opening zip file 
[typedef] at java.util.zip.ZipFile.open(Native Method) 
[typedef] at java.util.zip.ZipFile.<init>(ZipFile.java:214) 
[typedef] at java.util.zip.ZipFile.<init>(ZipFile.java:144) 
[typedef] at java.util.jar.JarFile.<init>(JarFile.java:153) 
[typedef] at java.util.jar.JarFile.<init>(JarFile.java:117) 
[typedef] at org.apache.tools.ant.AntClassLoader.getResourceURL(AntClassLoader.java:1014) 
[typedef] at org.apache.tools.ant.AntClassLoader$ResourceEnumeration.findNextResource(AntClassLoader.java:150) 
[typedef] at org.apache.tools.ant.AntClassLoader$ResourceEnumeration.<init>(AntClassLoader.java:111) 
[typedef] at org.apache.tools.ant.AntClassLoader.findResources(AntClassLoader.java:954) 
[typedef] at org.apache.tools.ant.AntClassLoader.getNamedResources(AntClassLoader.java:923) 
[typedef] at org.apache.tools.ant.loader.AntClassLoader5.getResources(AntClassLoader5.java:58) 
[typedef] at org.apache.tools.ant.taskdefs.Definer.resourceToURLs(Definer.java:360) 
[typedef] at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:246) 
[typedef] at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292) 
[typedef] at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source) 
[typedef] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
[typedef] at java.lang.reflect.Method.invoke(Method.java:601) 
[typedef] at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) 
[typedef] at org.apache.tools.ant.Task.perform(Task.java:348) 
[typedef] at org.apache.tools.ant.Target.execute(Target.java:435) 
[typedef] at org.apache.tools.ant.Target.performTasks(Target.java:456) 
[typedef] at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1393) 
[typedef] at org.apache.tools.ant.Project.executeTarget(Project.java:1364) 
[typedef] at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) 
[typedef] at org.apache.tools.ant.Project.executeTargets(Project.java:1248) 
[typedef] at org.apache.tools.ant.Main.runBuild(Main.java:851) 
[typedef] at org.apache.tools.ant.Main.startAnt(Main.java:235) 
[typedef] at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280) 
[typedef] at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109) 
[typedef] Could not load definitions from resource org/apache/maven/artifact/ant/antlib.xml. It could not be found. 

BUILD FAILED 
/letv/apps_install/thrift-0.9.1/lib/java/build.xml:279: Problem: failed to create task or type antlib:org.apache.maven.artifact.ant:remoteRepository 
Cause: The name is undefined. 
Action: Check the spelling. 
Action: Check that any custom tasks/types have been declared. 
Action: Check that any <presetdef>/<macrodef> declarations have taken place. 
No types or tasks have been defined in this namespace yet 

This appears to be an antlib declaration. 
Action: Check that the implementing library exists in one of: 
-/letv/apps_install/apache-ant-1.9.4/lib 
-/root/.ant/lib 
-a directory added on the command line with the -lib argument 


Total time: 2 seconds

解决方法:ant通过yum方式安装,默认版本1.7.1,自行安装最新版本1.9.4,成功编译后在当前目录生成了build文件夹,包括libthrift-0.9.1.jar以及依赖的lib:

commons-codec-1.6.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
httpclient-4.2.5.jar
httpcore-4.2.4.jar
junit-4.4.jar
log4j-1.2.14.jar
servlet-api-2.5.jar
slf4j-api-1.5.8.jar
slf4j-log4j12-1.5.8.jar

开发流程及代码示例

1,编写IDL文件helloService.thrift,如下:

/**

 * Hello world Testing

 *

 */

namespace java com.le.mms

service HelloService {

    i32 sayInt(1:i32 param)

    string sayString(1:string param)

    bool sayBoolean(1:bool param)

    void sayVoid()

}

2. 使用thrift编译器生成所需语言的代码

thrift --gen java helloService.thrift

在当前目录下生成gen-java目录,里面生成了HelloService.java文件。

Thrift --gen py helloService.thrift 可以生成python相关代码。

 

3. 新建Java工程或maven工程,java工程引入ant生成的lib,maven工程pom.xml中引入依赖。

   <dependency>

      <groupId>org.apache.thrift</groupId>

      <artifactId>libthrift</artifactId>

      <version>0.9.1</version>

    </dependency>

自动会将依赖的lib下载下来。

4. 编写HelloServiceImpl.java业务实现类. 需要实现HelloService.Iface接口,由thrift自动生成的代码。 

package com.le.mms.thrift; 

import org.apache.thrift.TException;

public class HelloServiceImpl implements HelloService.Iface{

    @Override

    public int sayInt(int param) throws TException {

        System.out.println("say int :" + param);

        return param;

    }

    @Override

    public String sayString(String param) throws TException {

        System.out.println("say string :" + param);

        return param;

    }

    @Override

    public boolean sayBoolean(boolean param) throws TException {

        System.out.println("say boolean :" + param);

        return param;

    }

    @Override

    public void sayVoid() throws TException {

        System.out.println("say void ...");

    }

}

 

5. 编写thrift-java服务器端,监听端口9090

package com.le.mms.thrift.server;

import org.apache.thrift.protocol.TBinaryProtocol;

import org.apache.thrift.protocol.TBinaryProtocol.Factory;

import org.apache.thrift.server.TServer;

import org.apache.thrift.server.TSimpleServer;

import org.apache.thrift.transport.TServerSocket;

import org.apache.thrift.transport.TTransportException;

import com.le.mms.thrift.HelloService;

import com.le.mms.thrift.HelloServiceImpl;

import com.le.mms.thrift.HelloService.Processor;

/**

 * 启动thrift的java服务器端

 *

 * @author david

 *

 */

public class HelloServiceServer {

   

    public static void main(String[] args) {

        try {

            // 设置服务器端口

            TServerSocket serverTransport = new TServerSocket(9090);

            // 设置二进制协议工厂

            Factory protocolFactory = new TBinaryProtocol.Factory();

            //处理器关联业务实现

            Processor<HelloService.Iface> processor = new HelloService.Processor<HelloService.Iface>(new HelloServiceImpl());

            // 1. 使用单线程标准阻塞I/O模型

            TServer.Args simpleArgs = new TServer.Args(serverTransport);

            simpleArgs.processor(processor);

            simpleArgs.protocolFactory(protocolFactory);

            TServer server = new TSimpleServer(simpleArgs);

            // 2. 使用线程池服务模型

//            TThreadPoolServer.Args poolArgs = new TThreadPoolServer.Args(serverTransport);

//            poolArgs.processor(processor);

//            poolArgs.protocolFactory(protocolFactory);

//            TServer poolServer = new TThreadPoolServer(poolArgs);

//            poolServer.serve();

            System.out.println("开启thrift服务器,监听端口:9090");

            server.serve();

        } catch (TTransportException e) {

            e.printStackTrace();

        }

    }

}

 

6.编写thrift-java客户端,发出请求。

package com.le.mms.thrift.client;

import org.apache.thrift.TException;

import org.apache.thrift.protocol.TBinaryProtocol;

import org.apache.thrift.protocol.TProtocol;

import org.apache.thrift.transport.TSocket;

import org.apache.thrift.transport.TTransport;

import org.apache.thrift.transport.TTransportException;

import com.le.mms.thrift.HelloService; 

/**

 * 调用thrift的java客户端

 *

 * @author david

 *

 */

public class HelloServiceClient {

   

    public static void main(String[] args) {

        try {

            // 设置调用的服务地址-端口

            TTransport transport = new TSocket("localhost", 9090);

            //  使用二进制协议

            TProtocol protocol = new TBinaryProtocol(transport);

            // 使用的接口

            HelloService.Client client = new HelloService.Client(protocol);

            //打开socket

            transport.open();

            client.sayBoolean(true);

            client.sayString("Hello world");

            client.sayInt(20141111);

            client.sayVoid();

            transport.close();

        } catch (TTransportException e) {

            e.printStackTrace();

        } catch (TException te) {

            te.printStackTrace();

        }

    }

}

以上编写完了server和client端代码,运行server开启监听。然后运行client就能够与server端进行rpc调用方式的通讯了。

分享到:
评论

相关推荐

    spark-hive-thriftserver_2.11-2.1.3-SNAPSHOT-123456.jar

    spark-hive-thriftserver_2.11-2.1.spark-hive-thrift

    编译的spark-hive_2.11-2.3.0和 spark-hive-thriftserver_2.11-2.3.0.jar

    spark-hive_2.11-2.3.0...spark-hive-thriftserver_2.11-2.3.0.jar log4j-2.15.0.jar slf4j-api-1.7.7.jar slf4j-log4j12-1.7.25.jar curator-client-2.4.0.jar curator-framework-2.4.0.jar curator-recipes-2.4.0.jar

    spark-hive-thriftserver_2.11-2.4.5.jar

    spark和hive结合依赖,如何使用请看我博客https://blog.csdn.net/z1987865446/article/details/109372818

    flume通过thrift协议收集日志-Python

    Thrift 是一个跨语言的服务框架,它允许在不同的编程语言之间进行高效的数据序列化和通信。 首先,我们需要了解 Flume 的基本架构。Flume 由源(Source)、通道(Channel)和 sink 组成。Source 负责接收数据,...

    高性能RPC框架 nfs-rpc.7z

    nfs-rpc框架很可能就是这样一种解决方案,它在处理大规模并发请求时具备高性能,适合于构建高可用、高并发的分布式应用。 高性能通常涉及到以下几个方面: 1. **并发处理**:nfs-rpc可能采用了多线程或者异步IO...

    Thrift RPC客户端的服务化框架代码

    Thrift RPC客户端的服务化框架代码主要涉及了两个关键概念:Thrift和RPC(Remote Procedure Call,远程过程调用)。Thrift是由Facebook开发的一种开源跨语言服务框架,它允许定义数据类型和服务接口,然后自动生成...

    java 手写rpc框架 rpc-server and rpc-client

    在这个Java手写RPC框架的项目中,我们主要关注两个核心部分:`rpc-server`和`rpc-client`。 ### 1. RPC服务器(rpc-server) `rpc-server`是RPC框架的提供者端,它承载了服务的实现并对外发布。以下是一些关键知识...

    thrift php教程thrift-tutorial-php-master.zip

    在本教程"thrift php教程thrift-tutorial-php-master.zip"中,我们将深入学习如何使用Thrift与PHP进行交互。 首先,Thrift的接口定义语言(IDL)是其核心特性之一,它允许我们以类似协议缓冲区(protobuf)的方式...

    thrift-zookeeper-rpc

    对于Thrift服务化的改造,主要是客户端,可以从如下几个方面进行: 1.服务端的服务注册,客户端自动发现,无需手工修改配置,这里我们使用zookeeper,但由于zookeeper本身提供的客户端使用较为复杂,因此采用curator...

    dubbo-rpc-thrift-2.8.4.jar

    java运行依赖jar包

    rpc-tiger:rpc框架

    二、项目结构rpc-tigerrpc-commonrpc-thriftrpc-nettyrpc-application-springrpc-thrift-springrpc-netty-spring模块说明rpc-common: 封装rpc框架的主要处理逻辑。支持协议扩展,实现协议的不同部分即可。rpc-thrift...

    workerman-thrift, Thrift RPC for php based on workerman..zip

    Thrift是由Facebook开发的一种跨语言的RPC框架,它通过定义服务接口和数据类型,自动生成各种编程语言的客户端和服务器端代码,使得开发者可以轻松地构建可扩展的网络服务。而workerman-thrift是基于PHP的工作人猿...

    thrift-0.9.3 Object-C

    thrift0.9.3支持 Object-C

    maven-thrift-plugin-0.1.11-sources.jar

    maven-thrift-plugin-0.1.11-sources.jar

    cassandra-thrift

    cassandra-thrift cassandra-thrift cassandra-thrift cassandra-thrift cassandra-thrift cassandra-thrift

    Netty4.1实战-手写RPC框架.pdf

    RPC是一种远程调用的通信协议,例如dubbo、thrift等,我们在互联网高并发应用开发时候都会使用到类似的服务。本专题主要通过三个章节实现一个rpc通信的基础功能,来学习RPC服务...- 手写RPC框架第三章《RPC中间件》

    maven-thrift-plugin-0.1.11.jar

    maven-thrift-plugin-0.1.11.jar

    thrift-master-0.9.3-for-vs2013-vs2015

    thrift 0.9.3 for vs2013/vs2015 直接打开 thrift-master-0.9.3\lib\cppVS2013\thrift.sln thrift-master-0.9.3\lib\cppVS2015\thrift.sln 编译即可

    thrift-rpc-client

    Thrift-RPC客户端是基于Apache Thrift框架实现的一种RPC(远程过程调用)客户端,它在分布式系统中广泛用于提供高效、跨语言的服务调用。Kafka-RPC客户端则是特指将Thrift应用于Apache Kafka的客户端,使得应用程序...

    Python库 | thrift_pyi-0.2.0-py3-none-any.whl

    Python库Thrift PyI是Apache Thrift在Python中的一个实现,它主要负责处理跨语言的服务定义、...通过这个压缩包,你可以快速集成Thrift到你的Python项目中,享受它带来的高性能、类型安全的远程过程调用(RPC)框架。

Global site tag (gtag.js) - Google Analytics