RPC框架之——thrift的深入理解(一)

这篇具有很好参考价值的文章主要介绍了RPC框架之——thrift的深入理解(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、thrift的基本介绍

1.1 thrift的定义

Thrift是一个轻量级、跨语言的RPC框架,主要用于各个服务之间的RPC通信,最初由Facebook于2007年开发,2008年进入Apache开源项目。它通过自身的IDL中间语言, 并借助代码生成引擎生成各种主流语言的RPC服务端/客户端模板代码。Thrift支持多种不同的编程语言,包括C++, Java, Python,PHP,Ruby, Erlang, Haskell, C#, Cocoa, Javascript, Node.js, Smalltalk, OCaml, Golang等,本系列主要讲述基于Java语言的Thrift的配置方式和具体使用。

1.2 thrift架构

Thrift技术栈分层从下向上分别为:传输层(Transport Layer)协议层(Protocol Layer)处理(Processor Layer)服务层(Server Layer)

  1. 传输层(Transport Layer):传输层负责直接从网络中读取和写入数据,它定义了具体的网络传输协议;比如说TCP/IP传输等。
  2. 协议层(Protocol Layer):协议层定义了数据传输格式,负责网络传输数据的序列化和反序列化;比如说JSON、XML、二进制数据等。
  3. 处理层(Processor Layer):处理层是由具体的IDL(接口描述语言)生成的,封装了具体的底层网络传输和序列化方式,并委托给用户实现的Handler进行处理。
  4. 服务层(Server Layer):整合上述组件,提供具体的网络IO模型(单线程/多线程/事件驱动),形成最终的服务。
    thrift rpc,rpc,网络协议,网络
    采用TCP/IP作为更底层的通信协议图:
    thrift rpc,rpc,网络协议,网络

1.3 thrift的基本特性

1.3.1 开发速度快
通过编写RPC接口Thrift IDL文件,利用编译生成器自动生成服务端骨架(Skeletons)和客户端桩(Stubs)。从而省去开发者自定义和维护接口编解码、消息传输、服务器多线程模型等基础工作。服务端:只需要按照服务骨架即接口,编写好具体的业务处理程序(Handler)即实现类即可。客户端:只需要拷贝IDL定义好的客户端桩和服务对象,然后就像调用本地对象的方法一样调用远端服务。
1.3.2 接口维护简单
通过维护Thrift格式的IDL(接口描述语言)文件(注意写好注释),即可作为给Client使用的接口文档使用,也自动生成接口代码,始终保持代码和文档的一致性。且Thrift协议可灵活支持接口的可扩展性。
1.3.3 学习成本低
因为其来自Google Protobuf开发团队,所以其IDL文件风格类似Google Protobuf,且更加易读易懂;特别是RPC服务接口的风格就像写一个面向对象的Class一样简单。初学者只需参照:http://thrift.apache.org/,一个多小时就可以理解Thrift IDL文件的语法使用。
1.3.4 多语言/跨语言支持
Thrift支持C++、 Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk等多种语言,即可生成上述语言的服务器端和客户端程序。
1.3.5 稳定/广泛使用
Thrift在很多开源项目中已经被验证是稳定和高效的,例如Cassandra、Hadoop、HBase等;国外在Facebook中有广泛使用,国内包括百度、美团小米、和饿了么等公司。

2、thrift的基本语法

2.1 thrift的IDL介绍

Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,这种语言就是IDL(InterfaceDescription Language)

Thrift 采用IDL(Interface Definition Language)来定义通用的服务接口,然后通过Thrift提供的编译器,可以将服务接口编译成不同语言编写的代码,通过这个方式来实现跨语言的功能

2.2 IDL的基本语法——基础类型

thrift rpc,rpc,网络协议,网络

2.3 特殊类型、集合容器

binary: 未编码的字节序列,是string的一种特殊形式;这种类型主要是方便某些场景下JAVA调用。JAVA中对应的是java.nio.ByteBuffer类型,GO中是[]byte

目前有三种容器类型:

thrift rpc,rpc,网络协议,网络

在使用容器类型时必须指定泛型,否则无法编译idl文件。其次,泛型中的基本类型,JAVA语言中会被替换为对应的包装类型。

2.4 常量及类型别名(Const&&Typedef)

//常量定义
const i32 MALE_INT = 1
const map<i32, string> GENDER_MAP = {1: "male", 2: "female"}
//某些数据类型比较长可以用别名简化
typedef map<i32, string> gmp

2.5 struct类型

在面向对象语言中,表现为“类定义”;在弱类型语言、动态语言中,表现为“结构/结构体”。定义格式如下

struct <结构体名称> {

<序号>:[字段性质] <字段类型> <字段名称> [= <默认值>] [;|,]
}

例如:

struct User{
    1: required string name, //该字段必须填写
    2: optional i32 age = 0; //默认值
    3: bool gender //默认字段类型为optional
}

struct bean{
    1: i32 number=10,
    2: i64 bigNumber,
    3: double decimals,
    4: string name="thrifty"
}

struct有以下一些约束:

  1. struct不能继承,但是可以嵌套,不能嵌套自己
  2. 其成员都是有明确类型
  3. 成员是被正整数编号过的,其中的编号使不能重复的,这个是为了在传输过程中编码使用
  4. 成员分割符可以是逗号(,)或是分号(;),而且可以混用
  5. 字段会有optional和required之分和protobuf一样,但是如果不指定则为无类型–可以不填充该值,但是在序列化传输的时候也会序列化进去,optional是不填充则不序列化,required是必须填充也必须序列化。
  6. 每个字段可以设置默认值
  7. 同一文件可以定义多个struct,也可以定义在不同的文件,进行include引入

2.6 枚举、异常

Thrift不支持枚举类嵌套,枚举常量必须是32位的正整数

    enum HttpStatus {
        OK = 200,
        NOTFOUND=404
    }

异常在语法和功能上类似于结构体,差别是异常使用关键字exception,而且异常是继承每种语言的基础异常类

exception MyException {
    1: i32 errorCode
    2: string message
}

service ExampleService {
    string GetName() throws (1: MyException e)
}

2.7 Service (服务定义类型)

service UserService {
User getById(1:i32 id)
bool isExist(1:string name)
}

编译后的内容

thrift rpc,rpc,网络协议,网络

2.8 Namespace (名字空间)

Thrift中的命名空间类似于C++中的namespace和java中的package,它们提供了一种组织(隔离)代码的简便方式。名字空间也可以用于解决类型定义中的名字冲突。由于每种语言均有自己的命名空间定义方式(如python中有module), thrift允许开发者针对特定语言

定义namespace

namespace java com.yogurt.test

转化后

package com.yogurt.test

3、thrift的快速使用

3.1 环境待建

thrift编译器的安装
参考文档:https://thrift.apache.org/docs/install/

windows 安装
下载地址:https://thrift.apache.org/download

centos 安装
参考文档:https://thrift.apache.org/docs/install/centos.html

本人是Windows系统,所以这里搭建Windows环境

3.1.1 下载windows的文件,重命名文件为thrift.exe

thrift rpc,rpc,网络协议,网络

3.1.2 环境变量配置

thrift rpc,rpc,网络协议,网络

配置PATH路径,我的路径为:E:\installation\thrift

thrift rpc,rpc,网络协议,网络

3.1.3 测试

thrift rpc,rpc,网络协议,网络

安装成功!

3.2 快速入门尝试下

3.2.1 编写Thrift文件
namespace java com.yogurt
    struct User{
        1:i32 id
        2:string name
        3:i32 age=0
    }
    
service UserService {
    User getById(1:i32 id)
    bool isExist(1:string name)
}

Thrift的相关命令:

# 生成java
thrift -gen java user.thrift

# 生成c++
thrift -gen cpp user.thrift

# 生成php
thrift -gen php user.thrift

# 生成node.js
thrift -gen js:node user.thrift

#可以通过以下命令查看生成命令的格式
thrift -help

//指定输出目录
thrift --gen java -o target user.thrift

进行编译:

thrift rpc,rpc,网络协议,网络

默认会放在当前路径下,我当前的路径是/User/asus

thrift rpc,rpc,网络协议,网络

3.2.2 编写代码

客户端代码

package com.yogurt;

import com.yogurt.Service.User;
import com.yogurt.Service.UserService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;

/**
 * @author yogurt
 * @Date 2023/2/26 - 18:36 - 2023
 */
public class client {

    public static void main(String[] args) {

        try{
            TSocket socket = new TSocket("localhost", 9000);
            // 指定二进制编码
            TBinaryProtocol protocol = new TBinaryProtocol(socket);
            UserService.Client client = new UserService.Client(protocol);
            socket.open();

            // RPC 调用
            User byId = client.getById(9000);
            System.out.println("byId = " + byId);
        }catch (Exception e){
            System.out.println(e);
        }
    }
}

服务端代码

package com.yogurt;

import com.yogurt.Service.Impl.UserServiceImpl;
import com.yogurt.Service.UserService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;

/**
 * @author yogurt
 * @Date 2023/2/26 - 18:27 - 2023
 */
public class SimpleService {

    public static void main(String[] args) {
        try{
            TServerSocket socket = new TServerSocket(9000);
            // 获取process
            UserService.Processor processor = new UserService.Processor(new UserServiceImpl());
            // 指定TBinaryProtocol
            TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();

            TServer.Args args1 = new TSimpleServer.Args(socket);
            args1.processor(processor);
            args1.protocolFactory(factory);

            TSimpleServer tSimpleServer = new TSimpleServer(args1);

            tSimpleServer.serve();
        }catch (Exception e){
            System.out.println(e);
        }
    }
}

结果

thrift rpc,rpc,网络协议,网络

thrift rpc,rpc,网络协议,网络

这是在单线程场景下的,后续将详细介绍多线程下的RPC调用文章来源地址https://www.toymoban.com/news/detail-795336.html

到了这里,关于RPC框架之——thrift的深入理解(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 10 - 网络通信优化之通信协议:如何优化RPC网络通信?

    微服务框架中 SpringCloud 和 Dubbo 的使用最为广泛,行业内也一直存在着对两者的比较,很多技术人会为这两个框架哪个更好而争辩。 我记得我们部门在搭建微服务框架时,也在技术选型上纠结良久,还曾一度有过激烈的讨论。当前 SpringCloud 炙手可热,具备完整的微服务生态,

    2024年02月11日
    浏览(25)
  • RPC分布式网络通信框架(二)—— moduo网络解析

    网络部分,包括寻找rpc服务主机,发起rpc调用请求和响应rpc调用结果,使用muduo网络和zookeeper 服务配置中心 (专门做服务发现) 其中MprpcApplication类负责框架的一些初始化操作,注意去除类拷贝构造和移动构造函数(实现单例模式)。其中项目还构建了MprpcConfig类负责读取服

    2024年02月17日
    浏览(38)
  • RPC分布式网络通信框架(一)—— protobuf的使用

    常见序列化和反序列化协议有XML、JSON、protobuf,相比于其他protobuf更有优势: 1、protobuf是二进制存储的,xml和json都是文本存储的。故protobuf占用带宽较低 2、protobuf不需要存储额外的信息。 json如何存储数据?键值对。例:Name:”zhang san”, pwd: “12345”。 protobuf存储数据的方式

    2024年02月16日
    浏览(43)
  • 【Flink网络通讯(一)】Flink RPC框架的整体设计

    我们从整体的角度看一下Flink RPC通信框架的设计与实现,了解其底层Akka通信框架的基础概念及二者之间的关系。   Akka是使用Scala语言编写的库,用于在JVM上简化编写具有可容错、高可伸缩性的Java或Scala的Actor模型。Akka基于Actor模型,提供了一个用于构建可扩展、弹性、快速响

    2024年02月21日
    浏览(32)
  • RPC分布式网络通信框架(三)—— 服务配置中心Zookeeper模块

    分布式系统存在的问题: 为了支持高并发,每个客户端都保存了一份服务提供者的 列表 。但是如果 列表 有更新,想要得到最新的URL列表(rpc服务的ip和端口号),必须要手动更新配置文件,很不方便。 如图所示,实例3挂掉了,但是 列表 并没有得到更新。 故需要动态的更

    2024年02月15日
    浏览(39)
  • [RPC]关于RPC的一点理解

    以下内容仅为个人理解,不作正确性保证,感谢批评指正 在分布式计算中,远程过程调用 (RPC) 是指计算机程序导致过程(子例程)在不同的地址空间(通常在共享网络上的另一台计算机上)中执行, 它的编码就好像是普通(本地)过程调用一样,程序员没有 显式 编码远程

    2024年02月10日
    浏览(29)
  • 深度思考rpc框架面经之五:rpc限流:rpc事务:tps测试

    是的,我可以为你提供关于RPC注册中心及其监控的相关信息。RPC注册中心是用于管理微服务之间调用关系的中心化服务,它可以帮助微服务发现和调用其他服务。而监控是确保微服务健康、稳定运行的重要手段,可以实时检测和报警系统中的异常情况。 对于RPC注册中心的监控

    2024年02月07日
    浏览(37)
  • 深度思考rpc框架面经之五:rpc熔断限流、rpc复用连接机制

    推荐文章:RPC实现原理之核心技术-限流熔断 限流是一种常见的系统保护手段。在分布式系统和微服务架构中, 一个接口的过度使用可能会导致资源的过载,例如CPU、内存、带宽等都可能成为瓶颈。为了避免系统崩溃,确保系统的可用性,并为所有用户提供公平和合理的服务

    2024年02月11日
    浏览(28)
  • RPC和HTTP协议

            RPC 全称(Remote Procedure Call),它是一种针对跨进程或者跨网络节点的应用之间的远程过程调用协议。         它的核心目标是,让开发人员在进行远程方法调用的时候,就像调用本地方法一样,不需要额外为了完成这个交互做过的编码。         为了达到

    2024年02月11日
    浏览(29)
  • Rust微服务杀手级应用终于来了!一个最像RPC框架的Rust-RPC框架

    https://github.com/kwsc98/krpc-rust 刚刚学习Rust语言或者没怎么了解Rust-RPC框架的同学,可能以为又是一个标题党了,但实际上了解过这部分的同学都知道,目前来说主流的Rust-RPC框架和实际定义的RPC框架还是有着很大的差别。我们先看一下隔壁Java是如何实现的,就拿本项目Java版本

    2024年01月23日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包