Thrift介绍和快速入门案例

246 阅读5分钟

参考up:孙哥
孙哥主页

Thrift的引言

Thrift特点


1.  Thrift是一个RPC框架:解决远端功能调用
2.  可以进行异构系统的RPC调用

*   什么是异构系统? 服务的提供者 和 服务的调用者  不同语言开发系统

3.  为什么在当前系统开发中  会存在异构系统的RPC?

*   存在异构系统的调用 Python ---->Hbase(Java)
*   遗留系统的整合

4.  设计一个异构系统的RPC,解决的核心问题是什么?

*   两个进程之间的通信-----网络完成    ip:port 建立网络连接,进行通信即可。
*   存在挑战:
    *   得需要精通不同编程语言的网络  IO 线程 等相关技术内容
    *   数据传输的格式 1. 字符串json传输慢   2.二进制的格式(语言的二进制格式可能不一样,做适配)
        

ThriftRPC 框架

  1. 基本概念:

是apache组织开源的一个顶级异构系统RPC框架,用于完成异构系统的RPC通信 支持多种语言:Java ,C++,PHP,Python ,Ruby.......

  1. 特点:

    1. 跨语言支持(同种语言的效率没有非异构框架块)
    2. 开发快速
    3. 学习简单 IDL语言
    4. 稳定
  2. Thrift的设计思想

  • 针对不同的编程语言提供了一个库(jar)
  • 作用:网络通信的代码 协议(序列化) 相关内容 java libthrift
  • IDL 语言 中立语言 用于服务发表
  • Thrift命令 把IDL 语言 自动转换成 需要的编程语言

ThriftRPC安装

:::info

  1. 安装--把IDL转换成具体语言的命令

::: 2.Thrift安装 3.针对不同的编程语言,引入相应的库

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

IDL 语法

:::info 安装IDL 语法插件 image.png

:::

  • 注释
# 单行注释
// 单行注释
/*
* 多行注释
* */
  • namespace
namespace java com.suns
namespace py com.suns
指定生成好的代码  包
  • 数据类型
  • 基本类型
i8   有符号的8位整数   byte
i16   有符号的16位整数   short
i32   int
i64   long
double double
bool   boolean
string String  " "  ' '  utf-8

  • 集合类型
list<T> 
set<T>
map<K,V>

map<i32,string> sex={1:"female",2:"male"}
list<i32> ages=[1,2,3,4]


    
  • 结构体 struct 自定义对象 等价于java中的类-->实体类
struct User{
1:string name,
2:i32 age,
3:list<i32>ages=[1,2,3,4]
  }

  struct 不能继承
  成员与成员的分割 可以用, ;
  结构体里面的每一个字段  都要进行编号 1,2,3....
  变量类型  变量名
  optional  可选的 默认为每一个成员加入的关键字
  代表这个字段在序列化过程中可选的。如果这个字段没有默认值,就不序列化,有就序列化
  required 必选 ,无论是否有值都序列化
  • 枚举(enum)
enum SEASON{
    SPRING=1,
    SUMMERT=2
    ...
}
不支持枪套,i32

  • 异常(Exception)
exception MyExeption{
    1:i32 errorCode
    2:string message
}
    
  • 服务 service
service UserService{
    bool login(1:string name,2:string password)
    void register(1:User user)//User IDL语言中的结构体
}

注意:
1. 异常的处理
service UserService{
    bool login(1:string name,2:string password) throws(1:MyException e,2:XXXException e)
    void register(1:User user)//User IDL语言中的结构体
}
2,oneway 表示客户端发起请求后不等待响应返回,只能和void这种方法配合
service UserService{
    bool login(1:string name,2:string password) throws(1:MyException e,2:XXXException e)
    oneway void register(1:User user)//User IDL语言中的结构体
}
3.继承
service BaseService{
    void m1(1:string name)
}
service UserService extends BaseService{
}

  • include :::info 作用:进行IDL模块化编程 suns.thrift struct User{ 1:string name }

suns2.thrift include "suns.thrift" service UserSerivice{ void register(1:test.User user) } :::

  • Thrift 将IDL生成对应代码的命令

thrift --gen java xxx.thrift -r递归创建,引用的文件 thrift -r --gen java xxx.thrift

Thrift RPC的开发

  • 环境搭建

安装Thrift 引入依赖

        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.19.0</version>
        </dependency>
  • 项目结构的定义 :::info client 客户端 server 服务端 common rpc编程共有的内容 1,实体内容2.服务的接口 :::

  • Thrift核心对象 :::info

  1. TTransport

作用:封装网络通信 TSocket 阻塞IO通信 TNonblockdingTransport 非阻塞网路通信 TFramedTransport 加入了封帧的操作 (半包 粘包

  1. TProtocol

处理的协议(序列化的方式) TBinayProtocol 二进制序列化 TJSONProtocol JSON进行序列化 TCompactProtocol 压缩方式 处理二进制

  1. TProcessor

整合 网络通信和 业务功能

  1. TServer 服务端

:::

Thrift-common

//这是一个thrift文件
namespace java com.suns
struct User{
1:string name,
2:string password
}

service UserService{
User queryUserByNameAndPassword(1:string name,2:string password)
void save(1:User user)
}

Thrift-service

public class UserServiceImpl implements UserService.Iface {
   @Override
   public User queryUserByNameAndPassword(String name, String password) throws TException {
      System.out.println("queryUserByNameAndPassword"+name+password);
      return new User("xiaojianr","123");
   }

   @Override
   public void save(User user) throws TException {
      System.out.println("save user is"+user.getName()+user.getPassword());

   }
}

Thrift 服务器

public class TestServer {
   public static void main(String[] args) throws TTransportException {
      //TTransport
      TServerTransport tServerTransport=new TServerSocket(9000);
      //TBinaryProtocol
      TBinaryProtocol.Factory factory=new TBinaryProtocol.Factory();
      //TProcessor 发布对应的功能
      UserService.Processor processor=new UserService.Processor(new UserServiceImpl());
      TSimpleServer.Args arg=new TSimpleServer.Args(tServerTransport);
      arg.protocolFactory(factory);
      arg.processor(processor);
      TServer tServer=new TSimpleServer(arg);
      tServer.serve();


   }
}

Thrift-Client

public class TestClient {
   public static void main(String[] args) throws TException {

      TTransport transport=new TSocket("localhost",9000);
      transport.open();
      TProtocol tProtocol=new TBinaryProtocol(transport);

      UserService.Client userService=new UserService.Client(tProtocol);

      User user=userService.queryUserByNameAndPassword("xiaoji","123");
      System.out.println(user);
   }
}

启动服务端,和客户端 image.png image.png

注意事项

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.32</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.6</version> <!-- 请使用你需要的版本 -->
    </dependency>

实战开发中的思考

在实战开发中,往往服务端的功能 其实以及开发完成了

1.  现有本地的功能,服务端的功能以及写好了
2.  根据系统的功能,才可能决定,这个服务发布成RPC

所以在发布RPC业务实现 IFace接口,主页通过原有的Service方法的调用,进行实现,这样维护性更好,实战中使用的就是这种方法

TServer 服务的相关内容

TServer类型

1.  带表的是Thrift开发中的服务器
2.  功能:服务的开启server()  服务的关闭 stop()
3.  阻塞 非阻塞 有没有线程池  Reactor模式

TsimpleServer: 阻塞  单线程的服务器
TThreadPoolServer: 阻塞 线程池的服务器
TNonBlockingServer: 非阻塞 单线程的服务器
TThreadSeletorServer: 实现了主从版的Reactor  (类似Netty)