从Demo理解Thrift Thrift和Dubbo的区别

文章目录

  • 安装
  • 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就可以使用了

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

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

相关文章

苹果电脑清理内存 怎么清理删不掉的软件

苹果电脑是很多人的首选&#xff0c;因为它有着优秀的性能和设计。但是&#xff0c;随着时间的推移&#xff0c;你可能会发现你的苹果电脑变得越来越慢&#xff0c;或者出现一些奇怪的问题。这可能是因为你的电脑内存不足&#xff0c;或者有一些删不掉的软件占用了你的空间和资…

非常非常实用!不能错过,独家原创,9种很少人听过,但却实用的混沌映射!!!以鲸鱼混沌映射为例,使用简便

很多人在改进的时候&#xff0c;想着增加混沌映射&#xff0c;增加初始种群的多样性&#xff0c;可是&#xff0c;大多数论文中常见的映射&#xff0c;都被别人使用了&#xff0c;或者不知道被别人有没有使用&#xff0c; 本文介绍9种很少人知道&#xff0c;但非常实用混沌映射…

完成源示例

本主题演示如何创作和使用自己的完成源类&#xff0c;类似于 .NET 的 TaskCompletionSource。 completion_source 示例的源代码 下面的列表中的代码作为示例提供。 其目的是说明如何编写自己的版本。 例如&#xff0c;支持取消和错误传播不在此示例的范围内。 #include <w…

isis实验

根据要求制作大概&#xff1a; 使用isis配置路由器&#xff1a; 配置好物理接口地址后配置isis 为实现r1访问r5的环回走r6,需要在r6上制作路由泄露&#xff1a; 在r5上产生r1的路由明细&#xff1a; 全网可达&#xff1a;

竞赛练一练 第28期:GESP和电子学会相关题目练习

CIE一级2023.03_足球射门练习 1. 准备工作 &#xff08;1&#xff09;选择背景Soccer&#xff0c;Soccer 2&#xff1b; &#xff08;2&#xff09;保留默认小猫角色&#xff0c;添加角色&#xff1a;Soccer Ball&#xff1b; &#xff08;3&#xff09;给Soccer Ball添加声…

【C++】“Hello World!“

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C ⚙️操作环境:Visual Studio 2022 ​ 2024.1.14 纪念一下自己编写的第一个C程序 #include<iostream>int main() {/*我的第一个C程序*/std::cout << "Hello world!:>" <<std::endl;ret…

vscode打开c_cpp_properties.json文件的一种方式

步骤一 点击win32 步骤二 点击json 自动生成了

小程序开发公司哪家好?哪家最好?

小程序具有轻量、聚焦、快捷等特点&#xff0c;这有别于 web 端类和移动端 app 类产品。 小程序的第一印象非常关键&#xff0c;因此对于首页设计&#xff0c;关键要加强注意力表达&#xff0c;给予用户尽可能直观的信息感知&#xff0c;加快建立其对于业务价值的兴趣&#xf…

C++ Webserver从零开始:基础知识(三)——Linux服务器程序框架

目录 前言 一.服务器编程基础框架 C/S模型 主要框架 二.I/O模型 阻塞I/O 非阻塞I/O 异步I/O 三.两种高效的事件处理模式 Reactor Proactor 四.模拟Proactor模式 五.半同步/半异步的并发模式 六.有限状态机 七.其他提高服务器性能的方法 池 数据复制 上下文切换…

前端性能优化之数据存取,存储以及缓存技术

无论是哪种计算机语言&#xff0c;说到底它们都是对数据的存取与处理。若能在处理数据前&#xff0c;更快地读取数据&#xff0c;那么必然会对程序执行性能产生积极的作用。 一般而言&#xff0c;js的数据存取有4种方式。 直接字面量:字面量不存储在特定位置也不需要索引&…

WEB前端人机导论实验-实训3超链接与多媒体文件应用

1.项目1 设计简易灯箱画廊 A.题目要求&#xff1a; 编程实现简易灯箱画廊&#xff0c;鼠标单击任一个图像超链接&#xff0c;在底部浮动框架中显示大图像&#xff0c;效果如下的页面。 B.思路: &#xff08;1&#xff09;CSS样式&#xff1a; a.在样式中对body元素进行居中…

力扣-盛最多水的容器

11.盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜…

性能篇:深入源码解析和性能测试arraylist和LinkedList差异!

嗨&#xff0c;大家好&#xff0c;我是小米&#xff01;今天我们要谈论的是 Java 中两个常用的集合类&#xff1a;ArrayList 和 LinkedList。大家都知道&#xff0c;这两者在新增和删除元素的操作上有一些差异&#xff0c;那么它们究竟在性能上有何表现呢&#xff1f;我们通过深…

Linux系统SSH远程管理服务概述

目录 一.SSH协议 1.定义 2.优点 &#xff08;1&#xff09;加密 &#xff08;2&#xff09;压缩 3.SSH的客户端与服务端 &#xff08;1&#xff09;客户端 &#xff08;2&#xff09;服务端 4.原理 5.实验&#xff1a;使用ssh远程登录 二.OpenSSH服务器 1.概念 2.…

自动执行 Active Directory 清理

Active Directory &#xff08;AD&#xff09; 可帮助 IT 管理员分层存储组织的资源&#xff0c;包括用户、组以及计算机和打印机等设备&#xff0c;这有助于管理员集中创建基于帐户和组的规则&#xff0c;并通过创建不合规的自动日志来强制执行和确保合规性。 不时清理AD是保…

详解SpringCloud微服务技术栈:认识微服务、服务拆分与远程调用

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;首期文章 &#x1f4da;订阅专栏&#xff1a;微服务技术全家桶 希望文章对你们有所帮助 在此之前&#xff0c;耗时半个月&#x…

哈希表的实现(2):拉链法实现哈希表

一&#xff0c;拉链法 在使用线性探测法实现哈希表时&#xff0c;会发生哈希冲突。这个时候就得向后找位置给新插入的值。这个过程无疑会对哈希表的效率有很大的影响。那我们能不能通过另一种方式来实现哈希表&#xff0c;让哈希表不会发生哈希冲突呢&#xff1f;答案当然是可以…

第二十八周:文献阅读笔记(弱监督学习)+ pytorch学习

第二十八周&#xff1a;文献阅读笔记&#xff08;弱监督学习&#xff09; 摘要Abstract1. 弱监督学习1.1. 文献摘要1.2. 引言1.3. 不完全监督1.3.1. 主动学习与半监督学习1.3.2. 通过人工干预1.3.3. 无需人工干预 1.4. 不确切的监督1.5. 不准确的监督1.6. 弱监督学习的创新点 2…

Vue-14、Vue绑定style样式

1、对象写法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>绑定css样式</title><!--引入vue--><script type"text/javascript" src"https://cdn.jsdelivr.net/npm/v…

数据结构:堆和堆排序

数据结构&#xff1a;堆和堆排序 文章目录 数据结构&#xff1a;堆和堆排序1.二叉树的存储结构1.顺序结构2.链式结构 2.堆3.堆的实现4.堆排序&#xff08;选择排序中的一类&#xff09;1. 基本思想2.代码实现 1.二叉树的存储结构 1.顺序结构 顺序结构存储就是使用数组来表示一…