一文学习Thrift RPC

Thrift RPC引言

Thrift RPC的特点

Thrift 是一个RPC的框架,和Hessian RPC有什么区别,最重要的区别是Thrift可以做异构系统开发。
什么是异构系统,服务的提供者和服务的调用者是用不同语言开发的。

为什么会当前系统会有异构系统的调用?
做大数据一般使用Python,数据存储又要使用Hbase(Java),这就是异构系统了。
另外,还有遗留系统额整合,一个公司的系统,是随着业务增长的,在不同的业务可能由不同的编程语言开发的,想要完成一个共同的目标,就要不同系统之间进行交互。不同的系统要传输数据,首先要构建一个统一的格式,和编程语言无关。

设计一个异构系统的RPC,解决的核心问题是什么?
只要双方用各自的编程语言,网络编程建立连接,进行通信即可。
但是有一些挑战:
1.得需要精通不同编程语言的网络IO线程技术。
2.通信数据的格式,尤其是二进制的格式,不同编程语言的二进制数据量大小不一样。
所以我们引入了Thrift帮我们解决异构系统的调用。

ThriftRPC框架

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

Thrift 命令的安装

安装什么?

安装的是将IDL语言转换为相应的编程语言。

如何安装

mac brew install thrift
windows http://www.apache.org/dyn/closer.cgi?path=/thrift/0.18.0/thrift-0.18.0.exe
https://blog.51cto.com/u_15854865/5810927

如何验证: thrift -help thrift --version

针对于不同的编程语言 安装库

这里用Java

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

IDL语法

IDEA 中 Thrift插件,插件目的提示 校验IDL语法。
IDL语法 必须 thrift

  • 注释

    #    单行注释
    //   单行注释
    /*
    *    多行注释 
    */
    
  • namespace

    namespace java com.liu
    namespace py com.liu
    
    指定编程语言,指定生成好的代码 包 
    
  • 基本类型

    1.  i8      有符号的8位整数   byte
    2.  i16     有符号的16位整数  short
    3.  i32     有符号的32位整数  int
    4.  i64     有符号的64位整数  long
    5.  double  64位浮点数       double
    6.  bool    布尔值          boolean
    7.  string  字符串 字符      "" ''  UTF-8
    
  • 集合类型

    list<T>   有序可重复    java.util.List 
    set<T>    无需不可重复  java.util.Set
    map<K,V>  k-v         java.util.Map
    
    map<i32,string> sex = {1:'female',2:'male'}
    list<i32> ages = [1,2,3,4]
    
  • struct 自定义对象

    struct User{
       1: string name ='sunshuai',
       2: optional i32 age,
       3: list<i32> ages = [1,2,3,4],
       4. required i32 hieght
    }
    
    1. struts 不能继承
    2. 成员与成员的分割,;
    3. 结构体里面的每一个字段 都要进行编号
    4. 变量类型 变量名
    5. optional 可选的 默认为每一个成员都加入的关键字
       代表这个字段在序列化过程中可选的。如果这个字段没有默认值,就不序列化,如果有默认值 就序列化.
    6. required 必选,有没有值都会序列化
    
  • 枚举 (enum)

    enum SEASON{
       SPRING = 1,
       SUMMERT = 2
       ...
    }
    
    不支持嵌套,i32 
    
  • 异常 (Exception)

    exception MyException{
       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

    作用:进行IDL模块化编程
    
    suns1.thrift
       struct User{
          1:string name
       }
    suns2.thrift 
       include "suns1.thrift"
       
       service UserService{
         void register(1:suns1.User user)
       
       }
    
  • Thrift把IDL生成对应代码的命令

    thrift --gen java xx.thrift 
    thrift --gen py xx.thrift
    
    thrift -r --gen java xx.thrift 
    

Thrift RPC的开发

环境搭建

1. 安装Thrift 作用:把IDL语言描述的接口内容,生成对应编程语言的代码,简化开发。
2. 引入依赖    作用:引入thrift针对于某一种编程语言的封装 (网络通信 协议【序列化】)
   <dependency>
      <groupId>org.apache.thrift</groupId>
      <artifactId>libthrift</artifactId>
      <version>0.13.0</version>
   </dependency>
   
  <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.9</version>
    </dependency>

项目结构的定义

1. thrift-client  代表的是服务的调用者
2. thrift-server  代表的是服务的提供者
3. thrift-common  RPC编程共有的内容 1,实体类型 2,服务接口

Thrift核心对象

1. TTransport
   作用:底层封装网络通信
   TSocket 阻塞IO通信
   TNonblockdingTransport 非阻塞网络通信
   TFramedTransport 加入了封帧的操作 (压缩后 数据边界问题)  
2. TProtocol
   处理的协议 (序列化方式)
   TBinayProtocol 二进制进行序列化
   TCompactProtocol 压缩方式 处理二进制 
   TJSONProtocol  JSON进行序列化
3. TProcessor
   业务处理:把通信数据 和 业务功能整合在一起
4. TServer 服务端

thrift-common

1. 通过IDL语言 定义 client与服务端 共用的数据类型 和 服务接口 
2. client server端 引入 common模块

编写thrift文件:

namespace java com.liu
struct User{
       1:string name,
       2:string password
}

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

使用Thrift工具命令生成文件放在common模块中。
在这里插入图片描述

服务端

1. 实现服务接口 :idl语言生成的
2. 创建服务端代码

在这里插入图片描述
服务端实现之后,就要发布服务,如何发布服务?

public static void main1(String[] args) throws TTransportException {
        //TTransport
        TServerTransport tServerTransport =new TServerSocket(9002);
        //TBinaryProtocol
        TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();
        //TProcessor
        UserService.Processor processor = new UserService.Processor(new UserServiceImpl());
        TSimpleServer.Args tArgs = new TSimpleServer.Args(tServerTransport);
        tArgs.protocolFactory(factory);
        tArgs.processor(processor);
        //TServer发布服务
        TServer tServer =new TSimpleServer(tArgs);
        tServer.serve();
    }

客户端

客户端要向本地方法那样 调用远端方法。 代理
 public static void main(String[] args) throws TException {
        //传输方式 基于Socket阻塞 也可以使用非阻塞方式
        TTransport transport=new TSocket("localhost",9002);
        //传输协议 TBinaryProtocol 二进制格式 TCompactProtocol 压缩格式 TJSONProtocol json格式
        TProtocol tProtocol =new TBinaryProtocol(transport);

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

        User user = userService.queryUserByNamendPassword("liusir", "123");
        System.out.println("user = " + user);

    }

启动服务端之后,然后运行客户端可以看到服务成功了。
在这里插入图片描述

实战开发中的思考

在实战开发中,往往服务端的功能 其实已经开发完成。
   1. 现有本地的功能 服务端的功能 写好了。
   2. 根据系统的功能,才有可能决定 这个服务发布成 RPC。
   
所以在发布RPC业务实现 IFace接口,主要通过原有的Service方法的调用,进行实现。这样维护性更好,也是实战中使用的方式。

TServer服务的相关内容

  • TServer类型

    1. 代表的是Thrift开发中的服务器。
    2. 功能:服务的开启serve()   服务的关闭stop()
    3. 阻塞 非阻塞 有没有线程池 Reactor模式
       TSimpleServer:        阻塞 单线程的服务器 (没有实战价值,只是用于测试)
       TThreadPoolServer:     阻塞 线程池的服务器 
       TNonBlockingServer:    非阻塞单线程的服务器 
       TThreadSelectorServer: 实现了主从版的Reactor(类似Netty)
    
  • 分析TSimpleServer

    目的:1. 了解Thrift相关类型的作用(源码的分析)
         2. 核实SimpleServer是一个阻塞的 单线程的服务器
    

    在这里插入图片描述

  • TThreadPoolServer

    阻塞,引入了线程池 
    
    1. 如果使用,一定注意 默认的线程池 最大值 Integer.Max显然不成 需要maxWorkerThreads进行设置。
    2. 不能够让我们的线程复用,因为没有selector
    
    底层实现思路 
       把具体调用的Socket分配 WorkerProcess进行操作,而WorkerProcess从线程池中获得 线程资源。
    
  • TNonblockingServer

    底层连接 必须使用 TFreameTransport ,TCompactProtocol

    非阻塞  单线程
    
    Java NIO 
    
    SocketChannel#configureBlocking
    ServerSocketChannel#configureBlocking
    
    selector
    
  • TThreadSelectorServer [主从版的Reactor模式的实现][实战中推荐]
    在这里插入图片描述

    • client

      public class TestClient1 {
          public static void main(String[] args) throws TException {
              //完成  与服务端 网络连接的连接
              TTransport tTransport = new TSocket("localhost", 9000);
              TFramedTransport tFramedTransport = new TFramedTransport(tTransport);
              tTransport.open();
      
              //创建协议
              TCompactProtocol tCompactProtocol = new TCompactProtocol(tFramedTransport);
      
              //创建代理  stub 存根 桩
              UserService.Client userService = new UserService.Client(tCompactProtocol);
      
              User user = userService.queryUserByNameAndPassword("xiaojr", "9090");
              System.out.println("user = " + user);
      
      
          }
      }
      
    • server

      public class TestServer1 {
          public static void main(String[] args) throws TTransportException {
              TNonblockingServerSocket tNonblockingServerSocket = new TNonblockingServerSocket(9000);
      
              TFramedTransport.Factory tFramedTransport = new TFramedTransport.Factory();
              TCompactProtocol.Factory factory = new TCompactProtocol.Factory();
      
              UserService.Processor processor = new UserService.Processor(new UserServiceImpl());
      
              TThreadedSelectorServer.Args arg = new TThreadedSelectorServer.Args(tNonblockingServerSocket);
              arg.transportFactory(tFramedTransport);
              arg.protocolFactory(factory);
              arg.processor(processor);
      
              TServer tServer = new TThreadedSelectorServer(arg);
              tServer.serve();
          }
      }
      
    • 1. client server thrift版本(maven) 一致
      2. client server通信的transport protocal 保持一致
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/347635.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flume介绍

一、介绍 Apache Flume 是一种分布式、可靠且可用的系统&#xff0c;用于有效地收集、汇总大量日志数据&#xff0c;并将其从多个不同来源转移到集中式数据存储区。 Apache Flume 的使用不仅限于日志数据聚合。由于数据源是可定制的&#xff0c;Flume 可用于传输大量事件数据&a…

C++学习| QT快速入门

QT简单入门 QT Creater创建QT项目选择项目类型——不同项目类型的区别输入项目名字和路径选择合适的构建系统——不同构建系统的却别选择合适的类——QT基本类之间的关系Translation File选择构建套件——MinGW和MSVC的区别 简单案例&#xff1a;加法器设计界面——构建加法器界…

红帽认证有啥用?初级红帽认证证书值得考吗?

大家好&#xff0c;这里是G-LAB IT实验室。 今天我们来了解一下Linux红帽认证。 红帽认证已成为企业和个人竞相追逐的热门资质。 红帽认证认可度究竟如何?红帽RHCSA认证含金量又有多高? 下面G-LAB将为你一一解答。 1 、红帽认证认可度怎么样&#xff1f; 事实上&#xff0…

git:git reset 和 git revert

在使用 git 进行项目开发的过程中&#xff0c;有时会出现错误提交的情况&#xff0c;这时就需要能够撤销错误的提交&#xff0c;将代码恢复到提交之前的样子。根据不同情况&#xff0c;可以使用 git reset 或 git revert 命令。 一. git reset git reset 的原理是修改 HEAD 的…

php怎么输入一个变量,http常用的两种请求方式getpost(ctf基础)

php是网页脚本语言&#xff0c;网页一般支持两种提交变量的方式&#xff0c;即get和post get方式传参 直接在网页URL的后面写上【?a1027】&#xff0c;如果有多个参数则用&符号连接&#xff0c; 如【?a10&b27】 post方式传参 需要借助插件&#xff0c;ctfer必备插…

羊奶与牛奶,谁更好?

羊奶与牛奶&#xff0c;谁更好&#xff1f; 羊奶和牛奶是我们日常饮食中常见的乳制品&#xff0c;但究竟哪种更好呢&#xff1f;今天就让小编羊大师带大家一起来探讨一下&#xff0c;看看羊奶和牛奶在各方面的优势和劣势&#xff0c;帮助你作出更明智的选择。 让我们从营养价…

仅使用 Python 创建的 Web 应用程序(前端版本)第07章_商品列表

在本章中,我们将实现一个产品列表页面。 完成后的图像如下 创建过程与User相同,流程如下。 No分类内容1Model创建继承BaseDataModel的数据类Item2MockDB创建产品表并生成/添加虚拟数据3Service创建一个 ItemAPIClient4Page定义PageId并创建继承自BasePage的页面类5Applicati…

常见算法思想:迭代法

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 学习必须往深处挖&…

vue3 实现百分比进度条,文件上传进度条,包更新进度条

包更新&#xff0c; 文件上传&#xff0c;进度条 template 里面 <van-button click"changerun">{{ run?暂停:播放 }}</van-button>{{ percentage }}%<div class"line" :style"{height:2px, width:percentage%, backgroundColor:perc…

Linux中的LVM理论

Linux LVM&#xff1a;Logical Volume Manager逻辑卷管理 无需在停机的情况下&#xff0c;动态调整分区的大小 PV里面的存在很多小方块PE&#xff08;物理扩展&#xff09;&#xff0c;一个PV继承了pp的100G&#xff0c;只不过被分开分配了 划分小的PE再存放在VG里面&#…

两相步进电机驱动原理

两相步进电机驱动 前言什么是步进电机驱动器细分控制电机内部结构图片步进电机驱动原理&#xff08;重要&#xff09;步进电机参数&#xff11;、步距角&#xff1a;收到一个脉冲转动的角度&#xff12;、细分数 &#xff1a;&#xff11;&#xff0f;&#xff12;&#xff0c…

常见の算法

前言本文主要使用Java 什么&#xff0c;是快乐星球#&#xffe5;%……什么是算法&#xff1f; 算法是一组完成任务的指令。任何代码片段都可视为算法&#xff0c;但我们主要介绍常见算法 一、引入——二分查找 二分查找是一种算法&#xff0c;其输入是一个有序的元素列表。如…

JSON-handle工具安装及使用

目录 介绍下载安装简单操作 介绍 JSON-Handle 是一款非常好用的用于操作json的浏览器插件&#xff0c;对于开发人员和测试人员来说是一款很好用的工具&#xff0c;如果你还没有用过&#xff0c;请赶紧下载安装吧&#xff0c;下面是安装过程和具体使用。 下载安装 点击下载JSON…

springboot项目快速引入knife4j

引入依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version> </dependency>knife4j配置文件 basePackage改为自己存放接口的包名 /*** Kn…

利用Redis List实现数据库分页快速查询的有效方法

目录 引言 传统数据库分页查询的挑战 Redis List的优势 利用Redis List实现分页查询 1. 数据准备 2. 分页查询 3. 分页缓存 4. 分页处理 结论 引言 随着Web应用程序的发展和用户数量的增加&#xff0c;数据库分页查询变得越来越常见。分页查询允许用户在大型数据集中…

python就业如何?和C++相比该选择哪个更好?

python就业如何&#xff1f;和C相比该选择哪个更好&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff…

深度学习与大数据在自然语言处理中的应用与进展

引言 在当今社会&#xff0c;深度学习和大数据技术的快速发展为自然语言处理&#xff08;NLP&#xff09;领域带来了显著的进步。这种技术能够使计算机更好地理解和生成人类语言&#xff0c;从而推动了搜索引擎、语音助手、机器翻译等领域的创新和改进。 NLP的发展与技术进步…

应用案例:Ruff工业设备数据采集,为生产制造企业数字化转型赋能

导读&#xff1a;某金属材料生产制造企业&#xff0c;引进了整套Ruff数据采集方案&#xff0c;将Ruff网关采集到的PLC数据接入到Ruff IoT管理云平台&#xff0c;帮助客户实现覆盖全厂区、车间所有设备的数字化、可视化管理&#xff0c;避免了意外停机风险&#xff0c;IT运维工作…

代码随想录算法训练营第29天(回溯算法05 | * 491.递增子序列 * 46.全排列 * 47.全排列 II

回溯算法part05 491.递增子序列解题思路与 90.子集II 不同的点回溯三部曲 46.全排列解题思路遇到的难点思考 47.全排列 II解题思路注意点拓展需要加深理解的点&#xff08;需复习 小总结 491.递增子序列 本题和大家刚做过的90.子集II非常像&#xff0c;但又很不一样&#xff0c…

服务器故障处理 | 浪潮SA5212H5服务器排查出现故障的内存条

服务器故障处理 | 浪潮SA5212H5服务器排查出现故障的内存条 浪潮SA5212H5服务器管理界面如下:    这个型号的浪潮服务器很特殊,没有内存条的硬件信息,也没有具体哪个位置的内存条出现故障,接下来需要去操作系统层面查看具体的信息。 为了摸清是哪些内存出了问题,…