【橘子分布式】Thrift RPC(理论篇)

一、简介

首先还是那句话,概念网上已经很多了,我们就不多逼逼了。我来大致介绍一下。

  1. Thrift是一个RPC框架
  2. 可以进行异构系统(服务的提供者 和 服务的调用者 不同编程语言开发系统)的RPC调用
  3. 为什么在当前的系统开发中,会存在着异构系统的RPC?
    1. 存在异构系统的调用
      Python ------> Hbase(Java)
      thrift
    2. 遗留系统的整合
  4. 设计一个异构系统的RPC 解决的核心问题是什么?
    肯定:异构系统的RPC 没有问题 只要双方 用各自的编程语言实现 网络编程中(client server)建立网络连接,进行通信即可。
    挑战:
    1. 得需要精通不同编程语言的网络 IO 线程等相关技术内容 (java go python c delphi…)
    2. 通信数据的格式,尤其是二进制的格式,得统一处理(中间的格式)

而thrift就是解决以上问题,作为rpc的框架封装出来给开发使用。

于是我们可以来看一下他的一些定义和性质特点。

1. 基本概念:是apache组织开源的一个顶级异构系统RPC框架,用于完成异构系统的PRC通信。
           多种编程语言 Java C++ PHP Phyton Ruby Node.js c# ....
           2007 FaceBook Thrift 开源。
2. 特点:
   1. 跨语言支持 
   2. 开发快速 
   3. 学习简单 IDL语言 
   4. 稳定 
   
3. Thrift的设计思想
   1. 针对于不同的编程语言提供了一个库(jar) 
      作用:网络通信的代码 协议(序列化)相关的内容  java libthrift 
   2. IDL语言 中立语言 用于服务发布
   3. Thrift命令把IDL语言 自动转换成 你需要的编程语言。

在这里插入图片描述
所以我们现在来总结一下,他就是个rpc框架,并且提供了多语言的异构,我们只需要编写对应的IDL中间语言文件.thrift文件,然后使用thrift命令,把这个idl中间文件编译成为目标语言的文件,这样就生成了对应的类。我们暂时先不说rpc的问题,这个放在我们的实践篇来说。

二、thrift的使用

1、ThriftRPC安装

我们需要去参考一下thrift官方文档,我们看一下其中的安装操作。
这个安装操作安装的就是把IDL转换成具体编程语言代码的命令。你可以理解为一个编译器。
在这里插入图片描述
我们可以看到他提供了多种操作系统的安装方式。
在这里插入图片描述
我们以mac为例,那就很简单了。

brew install thrift 

完成安装即可

 thrift -help
 thrift --version
 以上两个命令都可以用来验证是否安装成功。

因为我们是java环境,我们在java环境中开发的,所以我们需要安装一个库,针对于不同的编程语言 安装库

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

如果你是python那就pip install thrift ,每种语言都有自己的包管理方式。这里就不多说了。
然后我们还需要在idea中安装一下thrift的插件支持。
在这里插入图片描述
这个插件可以支持我们在idea中进行相应的idl开发。

2、IDL语法

我们上面说了,thrift对于多语言异构的支持是我们编写一份.thrift文件,这个文件称之为IDL,然后使用对应的命令来翻译成目标语言的文件,可见其核心就在这个IDL上,我们来看一下如何编写IDL的语法。
我们的目的是通过在thrift文件中定义相关的信息,然后通过thrift命令生成各种语言的代码,这里我们以java为例。

2.1、包路径:

namespace java com.levi.thrift // 定义java语言的包路径
namespace go levi.thrift // 定义go语言的包路径
namespace py levi.thrift // 定义python语言的包路径
namespace php levi.thrift // 定义php语言的包路径
namespace csharp levi.thrift // 定义c#语言的包路径
namespace cpp levi.thrift // 定义c++语言的包路径
namespace rb levi.thrift // 定义ruby语言的包路径
namespace perl levi.thrift // 定义perl语言的包路径
namespace nodejs levi.thrift // 定义nodejs语言的包路径
namespace lua levi.thrift // 定义lua语言的包路径
namespace dart levi.thrift // 定义dart语言的包路径
namespace rust levi.thrift // 定义rust语言的包路径
namespace swift levi.thrift // 定义swift语言的包路径
namespace kotlin levi.thrift // 定义kotlin语言的包路径
namespace typescript levi.thrift // 定义typescript语言的包路径

2.2、基本类型:

i8: 有符号8位整数类型  在java中就是byte 下面都是java的类型,其余的语言有自己的
i16: 有符号16位整数类型 在java中就是short
i32: 有符号32位整数类型 在java中就是int
i64: 有符号64位整数类型 在java中就是long
double: 64位浮点数类型 在java中就是double
string: 字符串类型 在java中就是String 在所有语言中就是UTF-8编码的字符串 可以是单引号也可以是双引号
binary: 二进制类型 在java中就是byte[]
void: 空类型 在java中就是void

2.3、集合类型:

list<T>  有序可重复类型 在java中就是java.util.List<T>
set<T>   无序不可重复类型 在java中就是java.util.Set<T>
map<K,V> 键值对类型 在java中就是java.util.Map<K,V>
举一个map的例子,如果你想生成一个Map<Integer,String>类型的代码,就要这样声明。
map<i32,string> sex = {1:"男",2:"女"}
集合类型是这样,list<i32> age = [1,2,3,4,5]

2.4、struct 自定义对象

在java中就是实体类,类似于c的结构体:

 struct User {
      1:i32 id,
      2:string name,
      3:i32 age
  }
  1、举一个struct的例子,如果你想生成一个User类型的代码,就要这样声明。里面有序号,类型,属性名称。
  2、struct的类不能继承,成员与成员之间的分割可以是逗号,也可以是分号。
  3、结构体里面的每一个字段都要进行编号,从1开始。
  4、结构是变量类型,变量名。
  5、还有一种类型,叫做optionl,就是可选类型,就是可以为空的类型,就是在序列化的时候是可选的,没有值就不序列化,有就序列化。
      默认为每一个成员都加入的关键字,可以不写。我上面就没写,其实默认就是。你妹提供默认值,他就不做序列化。
  6、还有一个关键字叫required,就是必须的,就是在序列化的时候是必须的,没有值就报错。和optionl相反。
      你妹提供默认值,他就报错。
  举个例子:其中email就是可选的,name就是必须要有值的。
  namespace java com.levi.entity
struct User{
 1: string name ='levi',
 2: optional i32 age,
 3: list<i32> ages = [1,2,3,4],
 4. required i32 hieght
}

2.5、enum 枚举类型

在java中就是枚举类:枚举以逗号分隔,并且不支持嵌套(枚举内部不能再定义枚举)
而且枚举中的整形只能是i32

namespace java com.levi.entity
enum Sex {
     MALE=1,
     FEMALE=2
 }

2.6、异常类型:

 exception 异常类型,在java中就是异常类:异常以逗号分隔也可以不分割,啥也不加都行,并且不支持嵌套(异常内部不能再定义异常)
    而且异常中的整形只能是i32
    namespace java com.levi.exception
    exception UserException {
        1: i32 code, 
        2: string message
    }

2.7、服务 (Service)

其实就是每种语言中的那些业务类。

服务接口 
service UserService{
   bool login(1:string name,2:string password)
   void register(1:User user) // 这个User不是实体类,而是我们前面定义的struct, idl语言中的结构体,也就是说你要先定义User这个结构体 
}

注意:
  1. 异常:throws关键字可以抛出异常之类的,异常列表里面可以有多个异常,这些异常也必须是我们前面定义的idl中的异常
     service UserService{
        bool login(1:string name,2:string password) throws (1:UserException e,2:XXXException e)
        void register(1:User user) // 这个User不是实体类,而是我们前面定义的struct, idl语言中的结构体,也就是说你要先定义User这个结构体 
      }
  3. oneway 表示客户端发起请求后不等待响应返回,立刻往下执行,因为没有返回值的概念,只能和void 这种操作配合。
      service UserService{
        bool login(1:string name,2:string password) throws (1:UserException e,2:XXXException e)
        oneway void register(1:User user) // 这个User不是实体类,而是我们前面定义的struct, idl语言中的结构体,也就是说你要先定义User这个结构体  
      }
  4. 继承,和struct不同,这里可以继承
     service BaseService{
        void m1(1:string name)
     }
     service UserService extends BaseService{
        
     }

2.8、include(模块化)

作用:进行IDL模块化编程
可以在一个thrift文件中,以include命令引入其他的thrift文件作为使用,最终生成的文件里面会引用,并且去掉前缀啥的。他的含义就是对应着你在一个类里面引用其他的包的类或者实体,这样的一个效果。
levi1.thrift
   struct User{
      1:string name
   }
levi2.thrift 
   include "levi1.thrift"
   
   service UserService{
     void register(1:levi1.User user)
   }

2.9、注释


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值