rpc远程协议之thrift入门

云水之路 云水之路     2022-12-07     620

关键词:

RPC远程协议之Thrift入门

 

在上一篇文章《RPC远程协议之原理分析》中,我介绍了RPC的工作原理及欲实现RPC框架功能应该做哪些事情,因为要做的事情太多,完全由开发人员研发实现,不是很现实,所以市面上出现了诸多RPC快捷框架,目前主流的有Facebook的Thrift、谷歌的gRPC,以及Dubbo,但就性能角度考虑,Thrift相对好些,并且是跨语言的,所以这里先以Thrift的介绍开始。对于Facebook,我们现阶段只需要知道它是一个高性能的、支持跨语言平台的远程服务调用框架,并且作为很多企业实现分布式系统架构的服务调用实现的基础,以及该怎样去使用它来快速搭建服务调用功能。

 

 

l  数据类型

l  准备条件

l  例子验证

 

 

一、数据类型

我们知道,Thrift是跨语言的RPC开源框架,那么它应该有自己的消息数据类型,而不是其它任何一门语言的数据类型,否则就不能支持其它语言,那么就看下它支持的几种定制类型,具体如下:

1、基础类型

类型

位数(有符号)

描述

bool

-

布尔类型,值为true或false

byte

8

字节类型,8位有符号整型数据

i16

16

整型类型,16位有符号整型数据

i32

32

整型类型,32位有符号整型数据

i64

64

整型类型,64位有符号整型数据

double

64

浮点类型,64位有符号浮点数字

string

-

文本类型,UTF-8格式字符串类型

为什么Thrift的数据类型都是有符号?因为很多语言都不支持无符号的数据类型,所以Thrift为了满足大部分语言特征,所以没必要加入无符号的数据类型。

 

2、特殊类型

binary,未经编码的字节流类型,主要针对字符串类型的字节流化,提供与java语言更好的互操作性。

 

3、结构类型

struct,定义普通的OOP类型,但不支持继承特性。

 

4、容器类型

list,一种有序的列表集合类型,如:对应java的List

set,一种无序的唯一值集合类型,如:对应java的Set

map,一种离散的键值对集合类型,如:对应java的Map

 

5、服务类型

service,定义对外提供的服务,如:供客户端使用的服务接口。

 

6、异常类型

exception,一种Thrift本身定制异常,与其它语言无缝结合的异常类型。

 

在下面的例子会演示基础类型、容器类型、结构类型,以及服务类型的使用,供读者参考。

 

二、准备条件

1、C/S双端

这里的C/S双端指的是客户端和服务端,实际使用时,客户端与服务端进程往往不在同一个节点中,比如:分布式环境,所以客户端和服务端一般是分离的,客户端需要引用由服务端所生成的服务代码,来完成远程调用。但在这里,我们将客户端与服务端代码均放在同一个项目中,所以客户端不需要额外引入即可使用调用,当然两端也分别在不同的进程中运行通信。

 

2、编译环境

下载地址:

http://thrift.apache.org/download

 

如果是mac osx则可以使用brew install thrift自动安装;

如果是linux系统,则可使用apt-get install thrift-compiler安装均可。

 

安装后,可以使用thrift –version查看版本,如果正常显示,则安装完成。

 

3、依赖添加

我这里采用maven来加载和管理thrift依赖包,并且使用最新版本0.11.0,具体配置如下:

<dependency>
  <groupId>
org.apache.thrift</groupId>
  <artifactId>
libthrift</artifactId>
  <version>
0.11.0</version>
</dependency>

 

 

三、例子验证

在这里,我就不以典型的helloworld为例,而是以根据用户ID获取用户基本信息和该用户的订单为例,详细介绍下Thrift的几种数据类的使用方法。

 

1、编写IDL文件(user.thrift)

# defaine the namespace
namespace java com.cwteam

# define the struct
struct User 
    1:i32 uid,
    2:string name,
    3:i16 sex,
    4:list<Order> orderList


struct Order 
    1:string oid,
    2:string oname,
    3:double price,
    4:i32 number,
    5:string createAt


# define the service
service UserService 
    # Get the user's order list by uid
    User getUserOrders(1:i32 uid)
    # Other operation follow here
    # ...

 

 

2、生成语言文件(UserService.java)

使用Thrift提供的编辑工具生成,切换到user.thrift文件所在目录,我的结构如下:

 

也就是user.thrift存放在main下,切换到main下,使用thrift命令编译生成语言文件,如下所示:

#thrift--gen java user.thrift

 

生成后的stub文件如下样子:

 

3、业务接口实现(UserHandler.java)

/**
 * 用户服务接口,由服务端负责实现
 */
public class UserHandler implements UserService.Iface 

    public User getUserOrders(int uid) throws TException 
        User user = new User();      // 模拟实现用户及订单查询
        user.setUid(uid);
        user.setName("David Lang");
        user.setSex((short)1);

        List<Order> orders = new ArrayList<Order>();
        Order order = new Order();
        order.setOid("NO1112321");
        order.setOname("Thrift进阶与提高》");
        order.setPrice(99.99);
        order.setNumber(1);
        order.setCreateAt("2017-04-04");
        orders.add(order);
        Order order2 = new Order();
        order2.setOid("NO1112322");
        order2.setOname("RPC进阶与提高》");
        order2.setPrice(88.88);
        order2.setNumber(2);
        order2.setCreateAt("2017-04-05");
        orders.add(order2);

        user.setOrderList(orders);
        return user;
    

 

 

4、服务端实例(UserServer.java)

/**
 * 将业务处理逻辑UserHandler作为具体的业务
 * 处理器,传递给Thrift服务器,执行处理逻辑.
 */
public class UserServer 
    private static final int port = 9081;
    private static UserHandler handler;
    private static UserService.Processor processor;

    /**
     * 启动服务端
     * processor为控制调用逻辑
     */
    public static void start(UserService.Processor processor) 
        try 
            // 阻塞方式,基于ServerSocket
            TServerTransport serverTransport = new TServerSocket(port);
            TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor));
            System.out.println("Starting simple server ...");
            // 启动服务
            server.serve();
         catch(Exception e) 
            e.printStackTrace();
        
    

    public static void main(String[] args) 
        handler = new UserHandler();
        processor = new UserService.Processor(handler);
        start(processor);
    

 

 

5、客户端实例(UserClient.java)

/**
 * 远程调用服务接口,获取用户信息及订单列表
 */
public class UserClient 
    private static final int port = 9081;
    private static final String addr = "localhost";

    private static UserService.Client client;
    private static TTransport transport;

    /**
     * 创建TTransport
     */
    private static TTransport createTTransport() 
        TTransport transport = new TSocket(addr,port);
        return transport;
    

    /**
     * 开启TTransport
     */
    private static void openTTransport(TTransport transport) throws TTransportException 
        if(null == transport) 
            return;
        
        transport.open();
    

    /**
     * 关闭TTransport
     */
    private static void closeTTransport(TTransport transport) 
        if(null == transport) 
            return;
        
        transport.close();
    

    /**
     * 创建客户端实体
     */
    private static UserService.Client createClient(TTransport transport) 
        if(null == transport) 
            return null;
        

        // 编码协议指定(这里是二进制方式传递)
        TProtocol protocol = new TBinaryProtocol(transport);
        if(null == protocol) 
            return null;
        

        // 设定编码协议
        UserService.Client client = new UserService.Client(protocol);
        return client;
    

    public static void main(String[] args) 
        try 
            transport = createTTransport();
            openTTransport(transport);
            client = createClient(transport);

            // 调用远程服务
            if(null == client) 
                System.out.println("客户端生成失败,不能调用服务 ...");
                return;
            
            User user = client.getUserOrders(10000021);
            System.out.println(user);
         catch(TException e1) 
            e1.printStackTrace();
        
    

 

 

6、例子运行结果

启动服务端:

 

启动客户端:

 

 

 

好了,Thrift入门就介绍到这里,读者也会发现这里所实现的服务调用方式为阻塞的,并且是非多线程的,所以在后续文章会继续介绍下阻塞多线程和非阻塞多线程的内容,敬请期待!

 

 

dubbo实现rpc调用使用入门

使用Dubbo进行远程调用实现服务交互,它支持多种协议,如Hessian、HTTP、RMI、Memcached、Redis、Thrift等等。由于Dubbo将这些协议的实现进行了封装了,无论是服务端(开发服务)还是客户端(调用服务),都不需要关心协议的细节,... 查看详情

rpc框架之thrift架构及源码解读

RPC远程过程调用之Thrift架构1.Thrift基本概念2.Thrift为什么可以跨语言?3.Thrift架构4.参考文献(源码解读)1.Thrift基本概念Thrift就是通过接口文件,来生成各语言的代码,接口文件以”*.thrift”命名。代码生成完&#... 查看详情

rpc框架之thrift架构及源码解读

RPC远程过程调用之Thrift架构1.Thrift基本概念2.Thrift为什么可以跨语言?3.Thrift架构4.参考文献(源码解读)1.Thrift基本概念Thrift就是通过接口文件,来生成各语言的代码,接口文件以”*.thrift”命名。代码生成完&#... 查看详情

rpc远程协议之原理分析

RPC远程协议之原理分析 在近几年工作中发现,功能服务化或微服务化越来越流行,逐渐成为实现中大型分布式系统架构的主要方式,而在分布式系统中的不同节点应用间的通信中,RPC远程协议扮演关键作用。实... 查看详情

消息总线扩展之集成thrift-rpc(代码片段)

...l,Haskell,C#,Cocoa,Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现。初衷做这件事情的初衷是RabbitMQ可以用于模拟request/response这样的通信模型,而这个通信模型就是通常C/S以及B/S架构的通信模型。并且因为RPC的... 查看详情

thrift

...  什么是RPC框架?    RPC全称为RemoteProcedureCall,意为远程过程调用.    假设有两台服务器A,B.A服务器上部署着 查看详情

grpc入门(代码片段)

...RPC简介在介绍gRPC之前先说一下RPC(RemoteProcedureCall),也叫远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。相比HTTP协议来说,它主要是基于TCP/IP协议的的,传输效率更高,... 查看详情

一个入门rpc框架的学习

...程序是一个短连接的rpc实现简介RPC,即RemoteProcedureCall(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样。RPC可基于HTTP或TCP协议,WebService就是基于HTTP协议的RPC,它具有良好的跨平台性,... 查看详情

rpc框架总述

RPC(RemoteProcedureCall):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。作者:李金葵来源:51CTO技术栈|2019-06-1708:21 收藏  分享【51CTO.com原创稿件】RPC(RemoteProcedureCall)... 查看详情

thrift快速入门

Thrift简单示例2017-01-1916:47:57首先通过先面两个示例简单感受一下Thrift(RPC)服务端与客户端之间的通信......RPC学习----Thrift快速入门和Java简单示例Thrift入门及Java实例演示Thrift是什么?Thrift源于大名鼎鼎的facebook之手,在2007年facebo... 查看详情

apachethrift系列详解-概述与入门

前言Thrift是一个轻量级、跨语言的远程服务调用框架,最初由Facebook开发,后面进入Apache开源项目。它通过自身的IDL中间语言,并借助代码生成引擎生成各种主流语言的RPC服务端/客户端模板代码。Thrift支持多种不同的编程语言,... 查看详情

rpc框架之thrift分析(转)

一、简介1、Thrift是Facebook开发的跨语言的RPC服务框架。随后贡献给Apache开源组织。成为RPC服务的主流框架。 2、特点: 优点:     跨语言,支持java、c/c++、python等多种编程语言     IDL... 查看详情

rpc框架

RPC(RemoteProcedureCallProtocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。Twitter的Finagle阿里巴巴的Dubbo当当网的Dubbo(即DubboeXtensions)新浪微博的Motanrpcx是Go语言生... 查看详情

springboot整合rpc框架---thrift

...,它被用来定义和创建跨语言的服务。它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的 查看详情

消息总线扩展之集成thrift-rpc(代码片段)

本文主要探讨了消息总线支持ThriftRPC的实现过程。鉴于RabbitMQ官方的JavaClient提供了基于RabbitMQ的JSON-RPC,消息总线也顺道提供了JSON-RPC的API。然后也尝试了为消息总线增加对Thrift-RPC的扩展支持,希望此举能让消息总线同时... 查看详情

rpc机制之amqp协议

...组件内部则采用了RPC通信。什么是RPCRPC即RemoteProcedureCall(远程方法调用),是Openstack中一种用来实现跨进程(或者跨机器)的通信机制。Opens 查看详情

thrift原理浅析

RPC原理RPC(RemoteProcedureCall )远程调用过程。1.定义了一个接口文件,描述了对象,对象成员,接口方法等一系列信息。2.通过RPC框架提供的编译器,将接口说明文件编译成对应的语言文件。2.在客户端和服务端分别引用RPC编译器生... 查看详情

thrift入门之helloworld

不多说,先看项目结构首先先编写一个hello.thrift的文件hello.thriftnamespacejavasawshawserviceHelloServicestringhello(1:stringmethod,2:stringparam) 注意了,这个namespace是 thrif根目录下tutorial目录的gen-java目录下的,如果没有这个目录,先cmd到tutoria... 查看详情