从Demo理解Thrift Thrift和Dubbo的区别

news2025/1/27 13:05:22

文章目录

  • 安装
  • demo尝试
  • Thrift协议栈
  • Thrift 与 Dubbo 的区别

字节里的RPC框架都是用的Thrift,我猜这主要原因有2:

  1. Thrift是Facebook开源的项目,平台中立
  2. Thrift支持跨语言调用,这非常适合字节Java、Go语言都存在的环境,语言中立

但是我对它的使用还不是很了解,因此找了一篇文章想上手做一些demo,参考Thrift 初认识 & Thrift 和Dubbo 的区别_dubbo和thrift的区别-CSDN博客

安装

brew install thrift 在 mac上就可以安装,很无敌,但是公司里好像不是这么干的

demo尝试

  1. 创建一个服务接口Hello,创建文件Hello.thrift,符合thrift的IDL规范

thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码,以满足不同需要的开发者。比如java开发者,就可以生成java代码,c++开发者可以生成c++代码,生成的代码中不但包含目标语言的接口定义、方法、数据类型,还包含有RPC协议层和传输层的实现代码。

比如代码如下:

namespace java service.demo
service Hello{
    string helloString(1:string para)
}
  1. 终端进入Hello.thrift所在目录,执行命令
 thrift -r -gen java Hello.thrift

发现在当前目录下多了一个gen-java的目录,里面的有一个Hello.java的文件。这个java文件包含Hello服务的接口定义Hello.Iface,以及服务调用的底层通信细节,包括客户端的调用逻辑Hello.Client以及服务端的处理逻辑Hello.Processor

  1. 创建一个Maven管理的Java项目,pom.xml中添加相关的依赖,并将Hello.java文件复制到项目中
<dependency>
    <groupId>org.apache.thrift</groupId>
    <artifactId>libthrift</artifactId>
    <version>0.19.0</version>
</dependency>
  1. 创建HelloServiceImpl首先Hello.Iface接口
package com.jxz.thriftdemo;

import com.jxz.thriftdemo.idl.Hello;
import org.apache.thrift.TException;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2024/1/14
 */
public class HelloServiceImpl implements Hello.Iface{
    @Override
    public String helloString(String para) throws TException {
        return "result = " + para;
    }
}

这里在编译的时候可能会找不到@javax.annotation.Generated,这是因为本地jdk版本较高导致的,可以直接删掉这个注解,它仅代表这个文件是自动生成的

  1. 创建服务端实现代码HelloServiceServer,把HelloServiceImpl作为一个具体的处理器传递给Thrift服务器
package com.jxz.thriftdemo.server;

import com.jxz.thriftdemo.idl.Hello;
import com.jxz.thriftdemo.impl.HelloServiceImpl;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2024/1/14
 */
public class HelloServiceServer {
    public static void main(String[] args) {
        try {
            System.out.println("服务端开启...");
            // 1. 创建TProcessor,传入处理器
            TProcessor tprocessor = new Hello.Processor<>(new HelloServiceImpl());
            // 2. 创建Tprotocol,这里采用二进制格式
            TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();
            // 3. 创建TserverTransport,监听端口
            TServerSocket serverTransport = new TServerSocket(8083);

            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(tprocessor);
            tArgs.protocolFactory(factory);
            // 4. 创建Tserver,传入需要的参数,server将以上内容集成在一起
            TSimpleServer server = new TSimpleServer(tArgs);
            // 5. 启动server
            server.serve();
        } catch (TTransportException e) {
            throw new RuntimeException(e);
        }
    }
}
  1. 创建客户端实现代码HelloServiceClient,调用Hello.client访问服务端的逻辑实现
package com.jxz.thriftdemo.client;

import com.jxz.thriftdemo.idl.Hello;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2024/1/14
 */
public class HelloServiceClient {
    public static void main(String[] args) {
        System.out.println("客户端启动...");
        TTransport tTransport = null;
        try {
            // 1. 创建TTransport
            tTransport = new TSocket("127.0.0.1", 8083, 5000);
            // 2. 创建Tprotocol,这里采用二进制格式
            TBinaryProtocol tProtocol = new TBinaryProtocol(tTransport);
            // 3. 创建TProcessor,由于这里需要用到具体的方法,因此不能用泛型
            Hello.Client client = new Hello.Client(tProtocol);
            // 4. 打开传输层
            tTransport.open();
            // 5. 启动client
            String result = null;
            result = client.helloString("hello world");
            System.out.println(result);
        } catch (TTransportException e) {
            throw new RuntimeException(e);
        } catch (TException e) {
            throw new RuntimeException(e);
        } finally {
            // 6. 最后关闭传输流
            if (null != tTransport) {
                tTransport.close();
            }
        }
    }
}

先启动服务端,然后启动客户端,最后客户端输出如下:

客户端启动...
result = hello world

可以明显地看出来,客户端RPC调用了服务端的方法,服务器里面的具体处理器为HelloServiceImpl对象

Thrift协议栈

在这里插入图片描述

Thrift是一种c/s的架构体系。Server主要任务是高效的接受客户端请求,并将请求转发给Processor处理。

  • 最上层是用户自行实现的业务逻辑代码;

  • Processor是由thrift编译器自动生成的代码,它封装了从输入数据流中读数据和向数据流中写数据的操作,它的主要工作是:从连接中读取数据,把处理交给用户实现impl,最后把结果写到连接上。

  • TProtocol(协议层),用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输,例如:

    • TBinaryProtocol:二进制格式;
    • TCompactProtocol:压缩格式;
    • TJSONProtocol:JSON格式;
    • TSimpleJSONProtocol:提供JSON只写协议, 生成的文件很容易通过脚本语言解析;
    • TDebugProtocol:使用易懂的可读的文本格式,以便于debug
  • TTransport(传输层),定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库

    • TSocket:阻塞式socker;
    • TFramedTransport:以frame为单位进行传输,非阻塞式服务中使用;
    • TFileTransport:以文件形式进行传输;
    • TMemoryTransport:将内存用于I/O,java实现时内部实际使用了简单的ByteArrayOutputStream;
    • TZlibTransport:使用zlib进行压缩, 与其他传输方式联合使用,当前无java实现
  • 底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。

  • Thrift支持的服务模型

    • TSimpleServer:简单的单线程服务模型,常用于测试;
    • TThreadPoolServer:多线程服务模型,使用标准的阻塞式IO;
    • TNonblockingServer:多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式);

Thrift 与 Dubbo 的区别

  1. 透明化服务调用

Thrift:通过IDL(接口定义语言)实现,Thrift是支持跨语言的,而要实现跨语言机制,就需要一种中间语言来完成,那就是IDL。首先定义好了IDL之后(即定义好了一个service),由于server和Client都需要持有这个与之语言相对应的服务接口,那就需要thrift来将IDL编译成与之语言相对应的接口类,比如server端是java,client端是C#,则server端需要编译成java类,client编译成C#类。然后server端负责接口的具体实现,client只需要持有这个对象接口,进行调用即可,然后通过网络通信传给server。server负责解析client传递过来的数据,由于服务对象接口统一为IDL(thrift格式),所以统一了解析形式,只和本地的开发语言有关。

Dubbo:通过java反射和动态代理实现这一功能,由于只支持Java,所以Client和Server端开发语言机制一样,所以它们能够通过spring框架进行依赖,server端一般将对象方法接口注册发布到Zookeper中,然后Client可以直接从Zookeper中获取server端发布的对象方法接口,这样Client可以通过Spring进行自动装配获得server端发布的对象方法服务接口。

  1. 网络通信

thrift 参考上文

Thrift实际上是实现了C/S模式,通过代码生成工具将thrift文生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后客户端调用服务,服务器端提服务便可以了。

dubbo网络通讯层主要实现了以下功能:

  • 多种网络通讯框架的抽象封装(netty,mina,grizzly)
  • 每个客户端主机和服务端保存单个长链接通信
  • 异步调用转同步
  • tcp链接的心跳和自动重连
  • 基于header头通讯协议,请求的编解码器

dubbo的网络通信基于NIO框架,一般基于事件的NIO网络框架都涉及到 channel , channelHandle核心概念,网络数据buffer, 网络数据编解码器,dubbo为了能够适配多种NIO框架,将以上概念全部又抽象了一层接口。如果有netty开发经验或者了解netty helloworld demo程序对于理解这个章节非常有帮助。

参考链接:

https://www.jianshu.com/p/1e0c8c08e89d

https://www.jianshu.com/p/1a1404ce2201

https://blog.csdn.net/qq418517226/article/details/51906357

  1. 序列化

thrift只支持对thrift协议描述的IDL进行序列化,包含如下几种序列化格式:

  • TBinaryProtocol:二进制格式;
  • TCompactProtocol:压缩格式;
  • TJSONProtocol:JSON格式;
  • TSimpleJSONProtocol:提供JSON只写协议, 生成的文件很容易通过脚本语言解析;
  • TDebugProtocol:使用易懂的可读的文本格式,以便于debug

dubbo支持各种协议的序列化,例如Hession,Jdk(实际上,dubbo没有IDL这一机制,因为实际上他就是通过java服务对象接口进行交互的)
例如他也可支持thrift协议,只需要thrift将IDL转换为一个java服务对象接口,那么dubbo就可以使用了

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

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

相关文章

手把手Docker部署Gitblit服务器

1拉取镜像 docker pull jacekkow/gitblit:v1.9.1 2.启动 docker run -d --name gitblit --restart always -p 10006:8080 -p 18443:8443 -p 19418:9418 -p 29418:29418 -v /data/gitblit/data:/opt/gitblit-data jacekkow/gitblit:v1.9.1 3.查看 默认账户/密码:admin/adm…

运算放大器相关知识总结(1)

1、 前言 最近做了一个小项目&#xff0c;这个项目是研发一款阻抗测量仪。这个阻抗测量仪可以测量人体在不同频率下的生物电阻抗&#xff0c;该设备的核心是模拟电路&#xff0c;技术难点是减小模拟电路噪声。该项目前前忙了2个多月&#xff0c;借着研发这个项目的机会把自己掌…

Jenkins-用户管理

用户管理 1 安装插件 2 选择安全策略为刚刚安装的插件 3 这个是安装插件以后会有的选项 4 增加一个角色 5 根据需要赋值角色的权限&#xff0c;并分配给用户

Protecting Intellectual Property of Deep NeuralNetworks with Watermarking

保护深度神经网络的知识产权与数字水印技术 ABSTRACT 深度学习是当今人工智能服务的关键组成部分&#xff0c;在视觉分析、语音识别、自然语言处理等多个任务方面表现出色&#xff0c;为人类提供了接近人类水平的能力。构建一个生产级别的深度学习模型是一项非常复杂的任务&a…

每日算法打卡:摘花生 day 14

文章目录 原题链接题目描述输入格式输出格式数据范围输入样例&#xff1a;输出样例&#xff1a; 题目分析示例代码 原题链接 1015. 摘花生 题目难度&#xff1a;简单 题目来源&#xff1a;《信息学奥赛一本通》 题目描述 Hello Kitty想摘点花生送给她喜欢的米老鼠。 她来…

机器学习_捕捉函数的变化趋势(凸函数)

文章目录 连续性是求导的前提条件通过求导发现 y 如何随 x 而变凸函数有一个全局最低点 机器学习所关心的问题之一捕捉函数的变化趋势&#xff0c;也就是标签&#xff08;y&#xff09;是如何随着特征字段&#xff08;x&#xff09;而变化的&#xff0c;这个变化趋势是通过求导…

Arm Generic Interrupt Controller v3 and v4(GICv3v4)学习(一)

提示 该博客主要为个人学习&#xff0c;通过阅读官网手册整理而来&#xff08;个人觉得阅读官网的英文文档非常有助于理解各个IP特性&#xff09;。若有不对之处请参考参考文档&#xff0c;以官网参考文档为准。 Arm Generic Interrupt Controller v3 and v4学习一共分为三章&…

【ArcGIS微课1000例】0088:计算城市建筑物朝向(矩形角度)

文章目录 一、实验描述二、实验数据三、角度计算1. 添加字段2. 计算角度四、方向计算一、实验描述 矩形要素具有长轴和短轴,其长轴方向也称为矩形面的主角度,可用于确定面要素的走向趋势。根据该方向参数,可以对具有矩形特征的地理对象进行方向分析,且适用于很多应用场景,…

利用PicGo和SM.MS图床工具实现Markdown(Typora)图片脱离本地路径

利用PicGo和SM.MS图床工具实现Markdown&#xff08;Typora&#xff09;图片脱离本地路径 文章目录 利用PicGo和SM.MS图床工具实现Markdown&#xff08;Typora&#xff09;图片脱离本地路径1.**前言:**2.解决方案2.1准备工具2.2. 工具介绍2.2.1. Typora2.2.2. SM.MS图床2.2.3. P…

如何使用手机公网远程访问本地群辉Video Station中视频文件【内网穿透】

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 1.使用环境要求&#xff1a;2.下载群晖videostation&am…

AnnData:单细胞和空间组学分析的数据基石

AnnData&#xff1a;单细胞和空间组学分析的数据基石 今天我们来系统学习一下单细胞分析的标准数据类型——AnnData&#xff01; AnnData就是有注释的数据&#xff0c;全称是Annotated Data。 AnnData是为了矩阵类型数据设计的&#xff0c;也就是长得和表格一样的数据。比如…

SpringMVC零基础入门 - 概述、入门搭建、PostMan的使用(常见数据类型的传输)、REST风格编程

SpringMVC零基础入门 - 概述、入门搭建、PostMan的使用(常见数据类型的传输)、REST风格编程 SpringMVC是隶属于Spring框架的一部分&#xff0c;主要是用来进行Web开发&#xff0c;是对Servlet进行了封装SpringMVC是处于Web层的框架&#xff0c;所以其主要的作用就是用来接收前…

cpp_11_虚函数_多态_纯虚函数

编译器根据指针的类型&#xff0c;来确定调用哪个类的普通成员函数 编译器根据基类类型指针指向的对象类型&#xff0c;来确定调用哪个类的虚函数 0 非虚的世界(全普通函数) 对象的自洽性&#xff1a; 1&#xff09;对同样的函数调用&#xff0c;各个类的对象都会做出恰当的…

WEB前端人机交互导论实验-实训2格式化文本、段落与列表

1.项目1 文本与段落标记的应用&#xff1a; A.题目要求: B.思路&#xff1a; &#xff08;1&#xff09;首先&#xff0c;HTML文档的基本结构是通过<html>...</html>标签包围的&#xff0c;包含了头部信息和页面主体内容。 &#xff08;2&#xff09;在头部信息…

Kubernetes (十二) 存储——Volumes配置管理

一. 卷的概念 官方地址&#xff1a;卷 | Kuberneteshttps://v1-24.docs.kubernetes.io/zh-cn/docs/concepts/storage/volumes/ 二. 卷的类型及使用 …

vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)

文章目录 ⭐前言&#x1f496;vue3系列相关文章 ⭐搭建vue3项目过程&#x1f496; 初始化项目&#x1f496; 添加antd和router依赖&#x1f496; vite配置项映射目录和代理&#x1f496; antd国际化&#x1f496; layout布局封装&#x1f496; vite读取modules目录文件作为路由…

【beyond compare】默认不比较文件结尾

默认不比较文件结尾 git服务端的代码是UNIX 编码的&#xff0c;但是本地visual studio 是PC的&#xff0c; 代码一样&#xff0c;但是编码不同&#xff0c;导致compare 无法区分。 这位大神解决了这个问题,亲测可用&#xff1a; Beyond Compare之PC与UNIX文件比较问题 感谢大…

【Java】JDBC 数据库连接 (JDK17+MySQL8)

文章目录 JDBC 是什么&#xff1f;导入JDBC jar包一、JDBC的核心API和使用路线二、基于 statement 演示 查询三、基于 statement 查询的改进与问题四、基于 preparedStatement 方式优化五、基于 preparedStatement 演示 CRUDC 、增加数据R、查询数据U、修改/更新 数据D、删除数…

Vant-ui图片懒加载

核心代码 在你的全局顶部引入和初始化 Vue.use(vant.Lazyload, {loading: /StaticFile/img/jiazai.jpg,error: /StaticFile/img/jiazai.jpg,lazyComponent: false, });//图片懒加载 <img v-lazy"https://img-blog.csdnimg.cn/direct/3d2c8a7e2c0040488a8128c3e381d58…

《教育界》期刊怎么投稿发表论文?

《教育界》是国家新闻出版总署批准的正规教育类期刊&#xff0c;由广西师范大学主管&#xff0c;广西师范大学出版社集团有限公司主办&#xff0c;面向国内外公开发行&#xff0c;旨在追踪教育新动向&#xff0c;探讨教育改革与管理、办学与教育教学经验等&#xff0c;为广大一…