`

远程服务调用框架 Apache Thrift

 
阅读更多

一、 Facebook 开发的远程服务调用框架 Apache Thrift,它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等创建高效的、无缝的服务,其传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势

 

二、Thrift实例 : 创建一个简单的服务Hello。

清单一 hello.thrift 

namespace java service.demo 
 service Hello{ 
  string helloString(1:string para) 
  i32 helloInt(1:i32 para) 
  bool helloBoolean(1:bool para) 
  void helloVoid() 
  string helloNull() 
 }

其中定义了服务Hello的五个方法,每个方法包括一个方法名,参数列表和返回类型。

使用Thrift工具编译Hello.thrift, 就会生成相应的Hello.java 文件。该文件包含了在Hello.thrift文件中描述的服务Hello的接口定义,即Hello.Iface接口。

创建 HelloServiceImpl.java 文件并实现 Hello.java 文件中的 Hello.Iface 接口,代码如下:

 
清单 2. HelloServiceImpl.java
 package service.demo; 
 import org.apache.thrift.TException; 
 public class HelloServiceImpl implements Hello.Iface { 
    @Override 
    public boolean helloBoolean(boolean para) throws TException { 
        return para; 
    } 
    @Override 
    public int helloInt(int para) throws TException { 
        try { 
            Thread.sleep(20000); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
        return para; 
    } 
    @Override 
    public String helloNull() throws TException { 
        return null; 
    } 
    @Override 
    public String helloString(String para) throws TException { 
        return para; 
    } 
    @Override 
    public void helloVoid() throws TException { 
        System.out.println("Hello World"); 
    } 
 }

 创建服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给 Thrift 服务器,代码如下:

 

 清单 3. HelloServiceServer.java

 package service.server; 
 import org.apache.thrift.TProcessor; 
 import org.apache.thrift.protocol.TBinaryProtocol; 
 import org.apache.thrift.protocol.TBinaryProtocol.Factory; 
 import org.apache.thrift.server.TServer; 
 import org.apache.thrift.server.TThreadPoolServer; 
 import org.apache.thrift.transport.TServerSocket; 
 import org.apache.thrift.transport.TTransportException; 
 import service.demo.Hello; 
 import service.demo.HelloServiceImpl; 

 public class HelloServiceServer { 
    /** 
     * 启动 Thrift 服务器
     * @param args 
     */ 
    public static void main(String[] args) { 
        try { 
            // 设置服务端口为 7911 
            TServerSocket serverTransport = new TServerSocket(7911); 
            // 设置协议工厂为 TBinaryProtocol.Factory 
            Factory proFactory = new TBinaryProtocol.Factory(); 
            // 关联处理器与 Hello 服务的实现
            TProcessor processor = new Hello.Processor(new HelloServiceImpl()); 
            TServer server = new TThreadPoolServer(processor, serverTransport, 
                    proFactory); 
            System.out.println("Start server on port 7911..."); 
            server.serve(); 
        } catch (TTransportException e) { 
            e.printStackTrace(); 
        } 
    } 
 }

创建客户端实现代码,调用 Hello.client 访问服务端的逻辑实现,代码如下:

清单 4. HelloServiceClient.java
 package service.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 service.demo.Hello; 

 public class HelloServiceClient { 
 /** 
     * 调用 Hello 服务
     * @param args 
     */ 
    public static void main(String[] args) { 
        try { 
            // 设置调用的服务地址为本地,端口为 7911 
            TTransport transport = new TSocket("localhost", 7911); 
            transport.open(); 
            // 设置传输协议为 TBinaryProtocol 
            TProtocol protocol = new TBinaryProtocol(transport); 
            Hello.Client client = new Hello.Client(protocol); 
            // 调用服务的 helloVoid 方法
            client.helloVoid(); 
            transport.close(); 
        } catch (TTransportException e) { 
            e.printStackTrace(); 
        } catch (TException e) { 
            e.printStackTrace(); 
        } 
    } 
 }

代码编写完后运行服务器,再启动客户端调用服务 Hello 的方法 helloVoid,在服务器端的控制台窗口输出“Hello World”(helloVoid 方法实现在控制台打印字符串,没有返回值,所以客户端调用方法后没有返回值输出,读者可以自己尝试其他有返回值方法的调用,其结果可以打印在客户端的控制台窗口 )。

 

三 数据类型

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:对应服务的类

四、协议

TBinaryProtocol 二进制编码格式进行数据传输

TCompactProtocol 高效率的、密集的二进制编码格式进行数据传输

TJSONProtocol 使用 JSON 的数据编码协议进行数据传输

TSimpleJSONProtocol 只提供 JSON 只写的协议,适用于通过脚本语言解析

 

五、传输层

TSocket —— 使用阻塞式 I/O 进行传输,是最常见的模式

TFramedTransport —— 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO(若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型)

TNonblockingTransport —— 使用非阻塞方式,用于构建异步客户端

 

六、服务端类型

TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O

TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O

TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O

 

七、Thrift 异步客户端构建

Thrift提供非阻塞的调用方式,可构建异步客户端。

 

清单 12.CallBack 的实现:MethodCallback.java

onComplete : 成功时,返回数据值

onError : 失败时,返回异常

 package service.callback; 
 import org.apache.thrift.async.AsyncMethodCallback; 

 public class MethodCallback implements AsyncMethodCallback { 
    Object response = null; 

    public Object getResult() { 
        // 返回结果值
        return this.response; 
    } 

    // 处理服务返回的结果值
    @Override 
    public void onComplete(Object response) { 
        this.response = response; 
    } 
    // 处理调用服务过程中出现的异常
    @Override 
    public void onError(Throwable throwable) { 

    } 
 }

 

 

清单 13.HelloServiceAsyncServer.java

HelloServiceAsyncServer 通过 java.nio.channels.ServerSocketChannel 创建非阻塞的服务器端等待客户端的连接。

 package service.server; 
 import org.apache.thrift.server.TNonblockingServer; 
 import org.apache.thrift.server.TServer; 
 import org.apache.thrift.transport.TNonblockingServerSocket; 
 import org.apache.thrift.transport.TNonblockingServerTransport; 
 import org.apache.thrift.transport.TTransportException; 
 import service.demo.Hello; 
 import service.demo.HelloServiceImpl; 

 public class HelloServiceAsyncServer { 
    /** 
     * 启动 Thrift 异步服务器
     * @param args 
     */ 
    public static void main(String[] args) { 
        TNonblockingServerTransport serverTransport; 
        try { 
            serverTransport = new TNonblockingServerSocket(10005); 
            Hello.Processor processor = new Hello.Processor( 
                    new HelloServiceImpl()); 
            TServer server = new TNonblockingServer(processor, serverTransport); 
            System.out.println("Start server on port 10005 ..."); 
            server.serve(); 
        } catch (TTransportException e) { 
            e.printStackTrace(); 
        } 
    } 
 }

 

创建异步客户端实现代码,调用 Hello.AsyncClient 访问服务端的逻辑实现,将 MethodCallback 对象作为参数传入调用方法中,代码如下:

清单 14.HelloServiceAsyncClient.java
 package service.client; 
 import java.io.IOException; 
 import org.apache.thrift.async.AsyncMethodCallback; 
 import org.apache.thrift.async.TAsyncClientManager; 
 import org.apache.thrift.protocol.TBinaryProtocol; 
 import org.apache.thrift.protocol.TProtocolFactory; 
 import org.apache.thrift.transport.TNonblockingSocket; 
 import org.apache.thrift.transport.TNonblockingTransport; 
 import service.callback.MethodCallback; 
 import service.demo.Hello; 

 public class HelloServiceAsyncClient { 
    /** 
     * 调用 Hello 服务
     * @param args 
     */ 
    public static void main(String[] args) throws Exception { 
        try { 
            TAsyncClientManager clientManager = new TAsyncClientManager(); 
            TNonblockingTransport transport = new TNonblockingSocket( 
                    "localhost", 10005); 
            TProtocolFactory protocol = new TBinaryProtocol.Factory(); 
            Hello.AsyncClient asyncClient = new Hello.AsyncClient(protocol, 
                    clientManager, transport); 
            System.out.println("Client calls ....."); 
            MethodCallback callBack = new MethodCallback(); 
            asyncClient.helloString("Hello World", callBack); 
            Object res = callBack.getResult(); 
            while (res == null) { 
                res = callBack.getResult(); 
            } 
            System.out.println(((Hello.AsyncClient.helloString_call) res) 
                    .getResult()); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
  } 
 }

 

分享到:
评论

相关推荐

    Apache Thrift——可伸缩的跨语言服务开发框架

    Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用框架。它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++,Java, Python,...

    Apache Thrift 使用说明

    Thrift 提供了一个集成的代码生成工具,允许开发者定义数据类型和服务接口,然后自动生成多种编程语言(如 C++ 和 Java)的客户端和服务器端代码,实现高效、可靠的远程过程调用(RPC)。 在 Ubuntu 系统下安装 ...

    Thrift在PHP中简单使用示例--远程服务调用框架

    Apache Thrift是一个强大的开源框架,它允许开发人员在多种编程语言之间进行高效的远程过程调用(RPC)。这个框架最初由Facebook开发,后来捐赠给了Apache软件基金会。Thrift的主要目标是解决多语言通信的问题,使...

    Apache Thrift 初学小讲(五)【代理】

    Apache Thrift 是一个开源的软件框架,用于构建可伸缩的、跨语言的服务。它结合了接口定义语言(IDL)来定义服务,编译器来生成代码,以及运行时库来支持多种编程语言间的通信。在"Apache Thrift 初学小讲(五)...

    Learning Apache Thrift

    5. **客户端调用**:在客户端,Thrift提供了客户端库,可以直接使用生成的接口调用远程服务。调用过程就像调用本地方法一样简单,Thrift会处理网络通信、序列化和反序列化等细节。 6. **多语言支持**:Thrift的一大...

    Apache Thrift 初学小讲(七)【负载均衡】

    Apache Thrift 是一个开源的软件框架,用于构建可伸缩的、高性能的跨语言服务。在本篇初学小讲中,我们将重点关注Thrift在负载均衡方面的应用,这对于构建大型分布式系统至关重要。Thrift通过提供一种高效的数据序列...

    Apache Thrift 初学小讲(六)【spring】

    它结合了接口定义语言(IDL)和编译器,允许开发者定义服务接口,然后自动生成多种编程语言的代码,使得在不同语言之间进行高效的数据序列化和远程过程调用成为可能。在本篇小讲中,我们将探讨如何将Thrift与Spring...

    Apache Thrift Java实战源码,包含了客户端和服务端源码

    Apache Thrift 是一款开源的软件框架,主要用于构建可扩展且跨语言的服务。它结合了编译器和库,能够高效地构建分布式系统。在Java领域,Thrift 提供了一种简洁的方式来实现远程过程调用(RPC)服务。在这个实战源码...

    Apache RPC调用实例

    Apache远程过程调用(Remote Procedure Call, RPC)是一种通信协议,允许网络上的一个程序调用另一个远程系统上的程序,并且看起来就像调用本地函数一样。在分布式系统中,RPC框架扮演着至关重要的角色,它简化了...

    Thrift框架使用分享

    Apache Thrift是由Facebook开发并开源的远程服务调用框架,它能够实现高效的跨语言服务开发和通信。Thrift框架通过接口描述语言(IDL)来定义服务,支持多种编程语言,如C++, Java, Python, PHP, Ruby, Erlang, Perl...

    【Thrift之C++远程调用helloworld菜鸟教程】

    Thrift是一种跨语言的服务开发框架,最初由Facebook开发,现在是Apache软件基金会的项目。它允许程序员定义服务接口,然后自动生成多种编程语言的代码,使得在这些不同的语言之间进行远程过程调用(RPC)变得容易。...

    基于thrift的rpc框架,在thrift基础上增加负载均衡,连接池,性能监控.zip

    在IT行业中,RPC(Remote Procedure Call)框架是分布式系统中常用的一种通信机制,它使得一个程序可以在不关心远程调用细节的情况下,像调用本地函数一样调用远程服务。Thrift是由Facebook开源的一个高性能、可扩展...

    Thrift--JSClient

    4. **服务调用**:演示如何在JavaScript中实例化Thrift客户端,连接到服务端,并执行远程过程调用(RPC)。 5. **跨平台通信**:可能涉及如何在Web应用中使用Thrift JSClient与后端服务(可能是Java、Python或其他...

    thrift阻塞与非阻塞模式下的测试

    RPC(Remote Procedure Call)是Thrift实现服务调用的核心机制,允许一个程序在不关心远程系统实现的情况下调用其提供的服务。 在Thrift中,有两种主要的通信模式:阻塞模式和非阻塞模式。这两种模式的设计目标在于...

    thrift多接口服务示例

    在传统的Thrift服务中,一个服务通常只包含一组相关的操作(即方法)。然而,在实际项目中,有时我们需要将不同的功能逻辑拆分为多个独立的服务接口,以便更好地管理和扩展系统。这就是“多接口服务”概念的由来。在...

    rpc远程调用

    总结,RPC远程调用是分布式系统中服务间通信的关键技术,它简化了跨网络的调用复杂性,让开发者可以像调用本地方法一样调用远程服务。各种RPC框架如gRPC、Dubbo等提供了不同的实现方式和优化策略,以满足不同场景下...

    基于Thrift框架RPC的研究与实现_田翠珍.pdf

    Apache Thrift 是一个高效、可扩展的跨语言通信框架,起源于Facebook,于2007年成为Apache软件基金会的开源项目。它被设计用来解决不同编程语言之间的数据交换问题,通过提供一套定义数据结构和服务的接口定义语言...

    thrift入门教程+代码

    Thrift适用于构建分布式系统中的RPC(远程过程调用)服务,能够降低跨语言、跨平台开发的复杂性,并且由于其高效的序列化和通信机制,性能表现良好。在实际应用中,Thrift常被用于构建大规模微服务架构,尤其是在...

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

    Python库Thrift PyI是Apache Thrift在Python中的一个实现,它主要负责处理跨语言的服务定义、编译器以及客户端和服务端的运行时框架。这个压缩包“thrift_pyi-0.2.0-py3-none-any.whl”是一个预编译的Python wheel...

    GO语言通过Thrift服务器和客户端通信(经典)

    Thrift是一种“编译时”的RPC(远程过程调用)框架,它通过定义服务接口和数据结构的IDL(接口定义语言)文件,自动生成不同语言的客户端和服务器端代码,使得跨语言通信变得简单。 **一、环境搭建** 在开始之前,...

Global site tag (gtag.js) - Google Analytics