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

 

l  数据类型

l  准备条件

l  例子验证

 

 

一、数据类型

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

1、基础类型

为什么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入门就介绍到这里,读者也会发现这里所实现的服务调用方式为阻塞的,并且是非多线程的。

原文:https://blog.csdn.net/why_2012_gogo/article/details/79432630

RPC远程协议之Thrift入门的更多相关文章

  1. RPC远程协议之原理分析

    在近几年工作中发现,功能服务化或微服务化越来越流行,逐渐成为实现中大型分布式系统架构的主要方式,而在分布式系统中的不同节点应用间的通信中,RPC远程协议扮演关键作用.实际上,在日常工作中,我们也多多少 ...

  2. Thrift入门初探--thrift安装及java入门实例

    什么是thrift? 简单来说,是Facebook公布的一款开源跨语言的RPC框架. 那么问题来了. 什么是RPC框架? RPC全称为Remote Procedure Call,意为远程过程调用. 假 ...

  3. Thrift入门及Java实例演示<转载备用>

    Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...

  4. 从0到1:全面理解RPC远程调用

    上一篇关于 WSGI 的硬核长文,不知道有多少同学,能够从头看到尾的,不管你们有没有看得很过瘾,反正我是写得很爽,总有一种将一样知识吃透了的错觉. 今天我又给自己挖坑了,打算将 rpc 远程调用的知识 ...

  5. Thrift入门初探(2)--thrift基础知识详解

    昨天总结了thrift的安装和入门实例,Thrift入门初探--thrift安装及java入门实例,今天开始总结一下thrift的相关基础知识. Thrift使用一种中间语言IDL,来进行接口的定义, ...

  6. Java自带RPC实现,RMI框架入门

    Java自带RPC实现,RMI框架入门 首先RMI(Remote Method Invocation)是Java特有的一种RPC实现,它能够使部署在不同主机上的Java对象进行通信与方法调用,它是一种 ...

  7. 2016windows(10) wamp 最简单30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world

    2016最简单windows(10) wamp 30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world thrift是什么 最简单解释 thrift是用来帮助各个编程语 ...

  8. Thrift入门 (一)

    Install Go to thrift page download thrift. 1 2 3 4 brew install boost ./configure --without-python s ...

  9. 測试JSON RPC远程调用(JSONclient)

    #include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...

随机推荐

  1. mybatis-plus 分页查询+ dao层抽象

    1.配置文件添加paginationInterceptor @Configuration @MapperScan("fama.cost.*.mapper") public clas ...

  2. 深度学习编译与优化Deep Learning Compiler and Optimizer

    深度学习编译与优化Deep Learning Compiler and Optimizer

  3. 深度人脸识别:CVPR2020论文要点

    深度人脸识别:CVPR2020论文要点 Towards Universal Representation Learning for Deep Face Recognition 论文链接:https:/ ...

  4. 硬件delay评估表

    硬件delay评估表 硬件延时评估表用于快速评估一个模型在特定硬件环境和推理引擎上的推理速度. Bw 主要用于定义PaddleSlim支持的硬件延时评估表的格式. 概述 硬件延时评估表中存放着所有可能 ...

  5. 我的N年软件测试感悟

    1.前言 大家好!我是Meng前段时间,很荣幸被一合作伙伴邀请发表一篇文章,主题为"这些年,我所从事软件测试的一些感悟",正好趁着这个机会,我也好好总结一下. 2.测试培训 对于软 ...

  6. java后端知识点梳理——多线程与高并发

    进程与线程 进程是一个"执行中的程序",是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体,一个进程中一般拥有多个线程. 线程和进程的区别 进程是操作系统分配资源的最小单 ...

  7. C语言const关键字的作用

    1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <string.h> 4 #include ...

  8. 如何使用 Python 统计分析 access 日志?

    一.前言 性能场景中的业务模型建立是性能测试工作中非常重要的一部分.而在我们真实的项目中,业务模型跟线上的业务模型不一样的情况实在是太多了.原因可能多种多样,这些原因大大降低了性能测试的价值. 今天的 ...

  9. 孟老板 Paging3 (一) 入门

    BaseAdapter系列 ListAdapter系列 Paging3 (一) 入门 Paging3 (二) 结合 Room Paging3 (一)  入门 前言: 官方分页工具,  确实香.   但 ...

  10. 如何优雅的实现Mysql 增删改查,看完你就会了

    接着上期说,上期没写一条sql就把数据查询出来了,那如果要保存或者更新数据怎么办呢?能不能自己写sql呢? 保存数据 @GetMapping("save")//保存数据 publi ...