一文学习Thrift RPC

news2024/11/17 0:04:00

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 保持一致
      

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3 Teleport 将组件传送到外层DOM位置

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

音频前置放大器电路图大全

音频前置放大器电路图&#xff08;一&#xff09; 在本设计中&#xff0c;前置放大器的增益控制采用直流音量控制方式&#xff0c;其具体实现如图1所示。前置放大器是由全差分运放和电阻构成的反相比例放大器&#xff0c;其增益由反馈电阻与输人电阻的比值决定。外部输人的直流…

【Leetcode】2859. 计算 K 置位下标对应元素的和

文章目录 题目思路代码结果 题目 题目链接 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 请你用整数形式返回 nums 中的特定元素之和 &#xff0c;这些特定元素满足&#xff1a;其对应下标的二进制表示中恰存在 k 个置位。 整数的二进制表示中的 1 就是这个整数的…

WebSocket实现HTML+SpringBoot聊天功能,小程序+SpringBoot聊天功能

目录 一、认识WebSocket 二、HTML实现聊天 三、微信小程序实现聊天 一、认识WebSocket 1.首先博主在初学Java时自我感觉走了很多弯路&#xff0c;因为以前见识短&#xff0c;在接触聊天功能时根本就没能想到有WebSocket这个聊天框架&#xff0c;就只能用底层的UDP或TCP实现聊…

基于Spring Boot的饮食分享平台设计与实现

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

vue项目打包部署到服务器并使用cdn加速

配置 vue.config.js文件 const isProd process.env.NODE_ENV production module.exports {// 其他配置chainWebpack: config > {// 生产环境下使用CDNif (isProd) {config.plugin(html).tap(args > {args[0].cdn assetsCDNreturn args})}},// 生产环境下替换路径为c…

第十二回 急先锋东郭争功 青面兽北京斗武-FreeBSD/Linux SSH配置和常用软件

周谨和杨志第一轮比枪&#xff0c;为了安全&#xff0c;将枪尖去掉&#xff0c;包上柔软的毡片&#xff0c;再蘸满石灰。两人打了四五十个回合&#xff0c;只见周谨身上斑斑点点&#xff0c;约有三五十处&#xff0c;而杨志身上只有左肩牌下一点白。 周谨不服又来比射箭&#x…

如何在云服务上通过docker部署服务?

如何在云服务上通过docker部署服务&#xff1f; 一、在云服务器上安装Docker1、查看云服务器的OS信息2、[安装Docker并使用&#xff08;Linux&#xff09;](https://help.aliyun.com/zh/ecs/use-cases/deploy-and-use-docker-on-alibaba-cloud-linux-2-instances) 二、通过dock…

互斥锁/读写锁(Linux)

一、互斥锁 临界资源概念&#xff1a; 不能同时访问的资源&#xff0c;比如写文件&#xff0c;只能由一个线程写&#xff0c;同时写会写乱。 比如外设打印机&#xff0c;打印的时候只能由一个程序使用。 外设基本上都是不能共享的资源。 生活中比如卫生间&#xff0c;同一…

视频尺寸魔方:分层遮掩3D扩散模型在视频尺寸延展的应用

▐ 摘要 视频延展(Video Outpainting)是对视频的边界进行扩展的任务。与图像延展不同&#xff0c;视频延展需要考虑到填充区域的时序一致性&#xff0c;这使得问题更具挑战性。在本文中&#xff0c;我们介绍了一个新颖的基于扩散模型的视频尺寸延展方法——分层遮掩3D扩散模型(…

Apollo Cyber RT:引领实时操作系统在自动驾驶领域的创新

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

Linux的常见指令和基本操作演绎【复习篇章一】

文章目录 前言下载安装 XShellXShell 下的复制粘贴热键操作01.ls指令tree 02.cd指令03.touch指令04.mkdir指令&#xff08;重要&#xff09;&#xff1a;05.rmdir指令 && rm 指令&#xff08;重要&#xff09;06.组合07.man指令&#xff08;重要&#xff09;&#xff1…

【lodash.js】非常好用高性能的 JavaScript 实用工具库,防抖,深克隆,排序等

前言&#xff1a;lodash是一款前端必须要知道的js库&#xff0c;它里面提供了许多常用的功能和实用的工具函数 基本上我参与的项目中都有lodash&#xff0c;只能说lodash太强大了&#xff0c;lodash.js 提供了超过 300 个实用的工具函数&#xff0c;涵盖了很多常见的编程任务 l…

群辉NAS的远程访问

群辉NAS是私有云存储&#xff0c;局域网访问很容易【详见&#xff1a;网上邻居访问设置、其它设备的访问设置】&#xff0c;远程访问相对复杂&#xff0c;涉及很多关键因素&#xff0c;现将过程记录如下&#xff1a; 目录 1、互联网接入 2、绑定MAC与IP地址 3、路由器开启5…

HTML5与App封装技术将网站一键打包成App

HTML5&#xff1a;跨平台的利器HTML5作为一种先进的网页标记语言&#xff0c;其最大的优势在于跨平台性。开发者仅需编写一次代码&#xff0c;即可在各种操作系统和设备上运行&#xff0c;无需为每个平台单独开发App。这种“编写一次&#xff0c;运行处处”的模式&#xff0c;大…

选择海外云手机需要考虑什么?

随着跨境电商行业的蓬勃发展&#xff0c;企业们纷纷寻找提升平台流量和广告投放效果的方法&#xff0c;这已成为业界的当务之急。传统的宣传模式在国内受到直播和链接带货等新兴方式的冲击&#xff0c;而在国外&#xff0c;类似的趋势也在悄然兴起&#xff0c;呈现出广阔的发展…

OOM 内存溢出与线上内存实时监控

单应用可用的最大内存 dalvik.vm.heapstartsize&#xff0c;它表示堆分配的初始大小。 APP启动的初始分配内存 dalvik.vm.heapgrowthlimit&#xff0c;它表示单个进程内存限定值。App最大内存限制 dalvik.vm.heapsize&#xff0c;单个进程可用的最大内存。开启largeHeap"t…

力扣646. 最长数对链

动态规划 思路&#xff1a; 思路与 力扣354. 俄罗斯套娃信封问题 类似将序列进行排序&#xff0c;然后假设 dp[i] 为第 i 个元素的最长数对链个数&#xff1b;则其状态转移方程&#xff1a; 第 i 个元素之前的某一个元素&#xff08;假设是下标是 j&#xff09;&#xff0c;如…

VS2022联合Qt5开发学习11(QT5.12.3联合VTK在VS2022上开发医学图像项目5——qvtkWidget上显示STL三维图像并取点)

这篇博文是接着这个系列前面的博文&#xff0c;来讲如何实现医学图像三视图同步视图。我想到的一个思路是用Scrollbar来控制切面的改变&#xff0c;还有一个想法是在三维图像上取点&#xff0c;然后以这个点为切面中心更新三维视图。这篇博文主要介绍的就是第二个想法的三维图像…

软件功能测试如何确定测试需求?CMA、CNAS软件测试报告获取

软件功能测试是为了验证软件的功能是否按照设计要求正常工作的过程&#xff0c;可以确保软件的质量&#xff0c;提高用户体验&#xff0c;也是保证软件安全和可靠性的重要一环。我们需要从多个角度对软件的各个功能模块进行测试&#xff0c;确保每个功能都能正常运行&#xff0…