当前位置: 首页 > news >正文

RPC通信相关

RPC

RPC, 远程过程调用(Remote Procedure Call,RPC)是一个计算机通信协议,该协议允许运行于一台计算机的程序程调用另一台计算机的上的程序。通俗讲,RPC通过把网络通讯抽象为远程的过程调用,调用远程的过程就像调用本地的子程序一样方便,从而屏蔽了通讯复杂性,使开发人员可以无需关注网络编程的细节,将更多的时间和精力放在业务逻辑本身的实现上,提高工作效率。

RPC本质上是一种 Inter-process communication(IPC)——进程间通信的形式。常见的进程间通信方式如管道、共享内存是同一台物理机上的两个进程间的通信,而RPC就是两个在不同物理机上的进程之间的通信。概括的说,RPC就是在一台机器上调用另一台机器上的方法,这种调用在远程机器上对代码的执行就像在本机上对代码的执行一样,只是迁移了一个执行环境而已。

RPC是一种C/S架构的服务模型,server端提供接口供client调用,client端向server端发送数据,server端接收client端的数据进行相关计算并将结果返回给client端。

执行一次RPC通常需要经历以下步骤(摘自 Wikipedia):

1.The client calls the client stub. The call is a local procedure call, with parameters pushed on to the stack in the normal way.

2.The client stub packs the parameters into a message and makes a system call to send the message. Packing the parameters is called marshalling.

3.The client's local operating system sends the message from the client machine to the server machine.

4.The local operating system on the server machine passes the incoming packets to the server stub.

5.The server stub unpacks the parameters from the message. Unpacking the parameters is called unmarshalling.

6.Finally, the server stub calls the server procedure. The reply traces the same steps in the reverse direction

为了实现上述RPC步骤,许多RPC工具被研发出来。这些RPC工具大多使用“接口描述语言” —— interface description language (IDL) 来提供跨平台跨语言的服务调用。现在生产中用的最多的IDL是Google开源的protobuf。

在日常开发中通常有两种形式来使用RPC,一种是团队内部完全实现上述RPC的6个步骤,自己序列化数据,然后自己利用socket或者http传输数据,最常见的就是游戏开发了。另一种就是利用现成的RPC工具,这些RPC工具实现了底层的数据通信,开发人员只需要利用IDL定义实现自己的服务即可而不用关心数据是如何通信的,最常见的RPC工具是Facebook开源的Thrift RPC框架。本文将重点讲解Thrift RPC。

Thrift实际上是实现了C/S模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。

Thrift的协议栈如下图所示:

在Client和Server的最顶层都是用户自定义的处理逻辑,也就是说用户只需要编写用户逻辑,就可以完成整套的RPC调用流程。用户逻辑的下一层是Thrift自动生成的代码,这些代码主要用于结构化数据的解析,发送和接收,同时服务器端的自动生成代码中还包含了RPC请求的转发(Client的A调用转发到Server A函数进行处理)。

协议栈的其他模块都是Thrift的运行时模块:

底层IO模块,负责实际的数据传输,包括Socket,文件,或者压缩数据流等。

TTransport负责以字节流方式发送和接收Message,是底层IO模块在Thrift框架中的实现,每一个底层IO模块都会有一个对应TTransport来负责Thrift的字节流(Byte Stream)数据在该IO模块上的传输。例如TSocket对应Socket传输,TFileTransport对应文件传输。

TProtocol主要负责结构化数据组装成Message,或者从Message结构中读出结构化数据。TProtocol将一个有类型的数据转化为字节流以交给TTransport进行传输,或者从TTransport中读取一定长度的字节数据转化为特定类型的数据。如int32会被TBinaryProtocol Encode为一个四字节的字节数据,或者TBinaryProtocol从TTransport中取出四个字节的数据Decode为int32。

TServer负责接收Client的请求,并将请求转发到Processor进行处理。TServer主要任务就是高效的接受Client的请求,特别是在高并发请求的情况下快速完成请求。

Processor(或者TProcessor)负责对Client的请求做出相应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理步骤。Processor是服务器端从Thrift框架转入用户逻辑的关键流程。Processor同时也负责向Message结构中写入数据或者读出数据。

Thrift的模块设计非常好,在每一个层次都可以根据自己的需要选择合适的实现方式。同时也应该注意到Thrift目前的特性并不是在所有的程序语言中都支持。例如C++实现中有TDenseProtocol没有TTupleProtocol,而Java实现中有TTupleProtocol没有TDenseProtocol。

利用Thrift用户只需要做三件事:

(1). 利用IDL定义数据结构及服务

(2). 利用代码生成工具将(1)中的IDL编译成对应语言(如C++、JAVA),编译后得到基本的框架代码(实现接口定义)

(3). 在(2)中框架代码基础上完成完整代码(纯C++代码、JAVA代码等)(实现业务逻辑)

Linux下安装

Thrift的安装包括上面提到生成代码生成器和应用框架库,网页(http://thrift.apache.org/docs/install/)描述了安装依赖项,除了gcc及其编译工具本身外,编译Thrift最大的依赖就是boost。安装过程并不复杂,请参阅相关网上文章。

Windows下Thrift的使用

下载thrift服务的安装包thrift-0.14.1.exe-其它文档类资源-CSDN下载 下载下来是一个.exe的运行文件

将下载下来的thrift-0.14.1.exe 文件重命名为thrift.exe

配置thrift的环境变量,即为了能够执行thrift指令

测试window环境thrift是否安装完成

Thrift基本概念与应用

Thrift有以下几个概念:

类型系统(typesystem)

Thrift定义了一套数据传输描述语言(有点类似IDL),它是“语言中性”的,这个就是它的类型系统。它分为五种类型(数据类型表达3种,预定义类/结构1种,接口表达1种):

基本类型(basictype),也就是bool、byte、i16、i32、i64、double、string,任何语言都有这些基本类型,比较有意思的是string,它即表达text,也表达binary bytes。另一个特点是整型没有unsigned,原因比较简单,因为有些语言不支持。

结构类型(struct):就是C语言中的struct,将基本类型组合起来。

容器类型(container):就是集合类型(list/set/map),其中的元素是任何Thrift可识别的基本、结构、容器类型。【不知道是否有不支持list/set/map的语言,那么Thrift如何处理呢?】

异常类型(exception):从数据结构讲就是结构类型,可以认为是便于异常的处理而单独拿出来的、预定义的、有特殊意义的结构类型。

服务定义类型(service):这个类型实际是用来定义接口的,Thrift代码生成器会根据这个定义,生成代码框架。

传输(transport)

也就是信息的传输渠道以及读写方式,例如,介质可以是socket、shared memory或file,Thrift规定了一些基本的操作(open/close/isOpen/read/write/flush,对server,再加上listen/accept)。特别的,针对Socket方式,有TScoket类,对file方式,有TFileTransport类,上面类比较底层,还有几个实用的类:TBufferedTransport,TFramedTransport,TMemoryBuffer等。

协议(protocol)

是对传输协议的封装,也就是传输采用二进制、XML或者text来表示信息,它的功能有两个:1.双向的消息队列;2.信息的编码和解码(也就是对上面类型的读/写)。关于流式格式,thrift数据类型是自我分割的,意思是说,thrift会自己在数据域的分割处插入标志,在解码的时候,即使没有数据域定义,thrift也能成功分割出各数据域。在若干篇文章中,都提到thrift的二进制流式编码有相当的效率(可以配合压缩),因此首选的协议应该是binary协议。

版本(versioning)

如果一个程序分开来开发,那版本问题就是绕不过去的问题。Thrift的版本是通过“field identifiers”来实现的,每个结构由其标识,结构中的每个域有其标识,这两个标识唯一决定了一个数据域。在解码的时候,数据域的标识被检查,如果不能识别,则该数据域被抛弃。Thrift也可以通过”Isset”机制来明确某些域的设置与否(发送端用来指明是否设置,接收端用来检测是否设置)。

四种情况:

添加了数据域, 旧客户端,新服务器端:客户端发送的数据中没有该域,服务器端能检测出来,可按缺省值处理。

删除了数据域, 旧客户端,新服务器端:客户端发送的数据中有该域,服务器端忽略该域。

添加了数据域, 新客户端,旧服务器端:客户端发送的数据中有该域,服务器端忽略该域。

删除了数据域, 新客户端,旧服务器端:客户端发送的数据中没有该域,服务器端可能不知道如何处理这种情况。

处理器(processor)

就是如何将各部分协调起来,形成代码(或用户代码的框架)。它有两个重要的类:TProcessor和TServer。TProcessor用来实现RPC调用,TServer是所有Server类的基类,TServer类主要处理连接和线程,而不管诸如传输、编码等。用户代码主要关注的一是.thrift文件,二就是这个接口。Thrift为此实现了TSimpleServer(单线程), TThreadedServer(每连接一个线程)和 TThreadPoolServer(线程池)等类。

下图是thrift生成代码的基本结构(C++)。

图中,ServiceIf是根据接口文件(.thrift)生成的虚接口类,用户的具体实现在ServiceHandler中。各种调用方式在TServer中实现。【详细的描述见实例】

2.Thrift实现上的几个考虑

目标语言

虽然有多种选择,但最常用的(可能也是支持最好的)是C++, Java, and Python。

生成的结构体

数据域成员都是公有的,没有set,get之类的东西,虽然建议采用isset,但也可以不用,系统足够强健来处理类似“FieldNotSetException”之类的问题,因而也没有涉及该异常。Read和write方面也是公有的,这样用户可以在固有的RPC之外来使用它们。

RPC方法标识:实现RPC时,建立函数名与函数指针之间的映射,大致如下(不同的语言表达方式不同,C++,map):

std::map<std::string,函数指针> processMap_;

这样加快函数调用。

多线程

对C++实现,在开发过程中,thrift开发人员研究过boost,ACE中与thread,timer相关的东西,开发人员不想引入过多的第三方依赖,因此thrift中只有对boost::shared_ptr的引用是必须的,但为了跨平台或获得更多的功能,一般情况下,boost中thread,timer及其依赖库也是需要的。

ThreadManager和TimerManager

线程管理类用来管理线程池,定时器管理类可以定时触发Runnable的对象,开启一件事情(可以放到或不放到一个单独线程)。

NonblockingOperation

这个东西需要libevent的支持。

Compiler(代码生成器)

这个东西是用C++写的,依赖于lex/yacc。代码生成分两步:第一,检查包含的文件和类型定义文件,生成“解析树”(the parse tree);第二,将各类型放到解析树中,根据解析树生成代码。

TFileTransport

这个类(及其继承类)可以将request消息记入文件,为提高性能,它先缓存记录,并存入磁盘。记录文件是分块的(文件固定大小),采用padding,记录不能跨块。

thrift示例

1、thrift的协议

namespace java com.wangyong.tripartite.wechat

service Hello {

string helloString(1:string word)

}

经过thrift服务进行编译会得到相应语言的接口

例如java的

thrift --gen java helloService.thrift

在当前目录下生成gen-java目录,里面生成了HelloService.java文件。

Thrift --gen py helloService.thrift 可以生成python相关代码。

使用java实现server方式

相关文章:

RPC通信相关

RPCRPC, 远程过程调用&#xff08;Remote Procedure Call&#xff0c;RPC&#xff09;是一个计算机通信协议&#xff0c;该协议允许运行于一台计算机的程序程调用另一台计算机的上的程序。通俗讲&#xff0c;RPC通过把网络通讯抽象为远程的过程调用&#xff0c;调用远程的过程就…...

Node.js + MongoDB 搭建博客 -- 登录页面

准备工作 安装Node.js安装express等相关库MongoDB数据库电脑系统&#xff1a;win11 功能分析 搭建一个简单的具有多人注册、登录、发表文章以及登出功能的博客。 设计目标 未登录&#xff1a;主页左侧导航栏显示home、login、register&#xff0c;右侧显示已发表的文章、发…...

互联网新理念,对于WEB 3.0 你怎么看?

WEB 3.0 这个名词走进大众视野已经有一段时间了&#xff0c;也曾在各个圈子里火热一时&#xff0c;至今各大互联网企业任旧在 WEB 3.0 上不断探索。但关于 WEB 3.0 是什么这个问题&#xff0c;其实大部分人都没有一个比较明确的认知&#xff0c;包括区块链和元宇宙等相关行业的…...

Git使用教程:最详细、最傻瓜、最浅显、真正手把手教

GITGIT版本控制版本控制的意义分布式图形化客户端环境搭建仓库的操作分支使用场景命令远程仓库操作生成公钥命令冲突忽略列表的配置时机配置方式版本回退练习&#xff1a;GIT 版本控制 把文件系统中的文件&#xff0c;按照修改的版本进行记录&#xff0c;进行管理的操作。 版…...

【面试题】Redis面试题汇总(无解答)

Redis为何这么快&#xff1f;缓存问题及解决入库和缓存策略问题及处理redis数据类型缓存过期删除策略内存淘汰机制Redis 回收进程如何工作的&#xff1f;Redis持久化RDB和AOFredis流式pipeline处理原生批命令 (mset, mget) 与 Pipeline 区别?Pipeline 有什么好处&#xff0c;为…...

RHCSA-用户和组管理和文件系统权限(3.11)

目录 用户&#xff08;UID&#xff09; 用户类别&#xff08;UID&#xff09;&#xff1a; 用户的增删改查&#xff1a; 修改用户密码&#xff1a; 查看用户是否存在&#xff1a; 组&#xff08;GID&#xff09; 组的增删改查&#xff1a; 设置组密码&#xff1a; 用户…...

RK3588平台开发系列讲解(同步与互斥篇)信号量介绍

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、信号量介绍二、信号量API1、结构体2、API三、函数调用流程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢上一章我们看了自旋锁的原理,本章我们一起学习下信号量的用法。 一、信号量介绍 和自旋锁一样,…...

One-YOLOv5 v1.2.0发布:支持分类、检测、实例分割

One-YOLOv5 v1.2.0正式发布。完整更新列表请查看链接&#xff1a;https://github.com/Oneflow-Inc/one-yolov5/releases/tag/v1.2.0&#xff0c;欢迎体验新版本&#xff0c;期待你的反馈。 1 新版本特性 1. 同步了Ultralytics YOLOv5的上游分支v7.0&#xff0c;同时支持分类、目…...

Zookeeper的Java API操作

Zookeeper的Java API操作一、先启动Zookeeper集群二、IDEA 环境搭建三、创建子节点四、获取子节点并监听节点变化五、判断 Znode 是否存在六、Watcher工作流程一、先启动Zookeeper集群 二、IDEA 环境搭建 1.创建一个Maven工程&#xff1a;ZookeeperProject 2.在pom.xml文件添…...

Web3:前端知识和后端知识基础

三.Web3:前端知识和后端知识基础 1.了解前端开发 2.了解JSP 3.了解JAVAWeb的三大组件 4.Servlet的使用 5.Filter的使用 6.了解thymeleaf 未更新 三.Web3:前端知识和后端知识基础 1.了解前端开发 ①前端架构 HTML超文本标记语言CSS层叠样式表JavaS...

调试射频TX和rx实验工程出现的问题与反思

1.今天用ADS仿真 发现 加上SMA 插损就到了4db&#xff0c;但是直接用传输线就在1db以内 这个问题我目前想到的排查思路是换成IPEX&#xff0c; 换成IPEX插损就变成2db 拿最新的7626去看 看到上面是SMA-3G 小针 还是结合参考的demo PCB来看 2.用射频的ipex测试LNA 发现校准…...

代码随想录刷题-数组总结篇

文章目录数组二分查找原理习题题目1思路和代码题目-2移除元素习题我的想法暴力解法双指针有序数组的平方习题暴力排序双指针长度最小的子数组习题暴力解法滑动窗口螺旋矩阵 II习题我的解法别人的解法总结数组 二分查找 本节对应代码随想录中&#xff1a;代码随想录-二分查找 …...

Qt读xml文件

QXmlStreamReaderQXmlStreamReader类通过简单的流式API为我们提供了一种快速的读取xml文件的方式。他比Qt自己使用的SAX解析方式还要快。所谓的流式读取即将一个xml文档读取成一系列标记的流&#xff0c;类似于SAX。而QXmlStreamReader类和SAX的主要区别就是解析这些标记的方式…...

Qt样式表

1>样式表介绍 样式表可通过 QApplication::setStyleSheet()函数将其设置到整个应用程序上&#xff0c;也可以使用 QWidget::setStyleSheet()将其设置到指定的部件或子部件上&#xff0c;不同级别均可设置样式表&#xff0c;称为样式表的层叠。样式表也可通过设计模式编辑样…...

Docker与微服务实战2022

基础篇(零基小白)1.Docker简介1.1 是什么问题&#xff1a;为什么会有docker出现&#xff1f;您要如何确保应用能够在这些环境中运行和通过质量检测&#xff1f;并且在部署过程中不出现令人头疼的版本、配置问题&#xff0c;也无需重新编写代码和进行故障修复&#xff1f; 答案就…...

Linux(传输层二)

文章目录0. 前言1. TCP协议1-1 TCP协议段格式1. TCP如何解包&#xff1f;2. TCP协议如何交付&#xff08;应用层- - 客户&#xff09;&#xff1f;3. 如何理解报文本身&#xff1f;4. 如何理解报文字段&#xff1f;1-2 确认应答(ACK)机制1-3 超时重传机制1-4 连接管理机制1. TC…...

4.Spring Cloud (Hoxton.SR8) 学习笔记—Nacos微服务治理、Nacos配置管理

本文目录如下&#xff1a;一、Nacos微服务治理Nacos 下载 与 启动Spring Cloud 集成 NacosIDEA 同一个 Application 启动多次Nacos - 配置集群Nacos - 设置负载均衡Nacos - 设置服务实例的权重二、Nacos 配置管理Nacos - 合理的把配置信息迁移到 Nacos 中Nacos - 配置命名规范N…...

卷王都在偷偷准备金三银四了...

年终奖没发&#xff1b; 简历石沉大海&#xff1b; 发消息只读不回 打开某招聘&#xff0c;看了看岗位&#xff0c;这个厂还不错&#xff0c;可是要求好高&#xff0c;我啥都不会。 “哎&#xff0c;算了&#xff0c;我简历还没更新呢&#xff0c;我躺到6月份拿到年终奖再跑…...

【C++的OpenCV】第十二课-OpenCV图像常用操作(九):找到图像的边界(轮廓)findContours()和drawContours()

&#x1f389;&#x1f389;&#x1f389;欢迎各位来到小白piao的学习空间&#xff01;\color{red}{欢迎各位来到小白piao的学习空间&#xff01;}欢迎各位来到小白piao的学习空间&#xff01;&#x1f389;&#x1f389;&#x1f389; &#x1f496;&#x1f496;&#x1f496…...

传奇开服流程—传奇单机架设教程

现在传奇私服还是那么的火爆&#xff0c;上次有报道发布站一年盈利几个亿&#xff0c;还是有很大的机会&#xff0c;很多玩家因为GM开服关服给折腾&#xff0c;刚充的钱服务器就关了&#xff0c;很是恼火&#xff0c;于是都想自己整个服开开&#xff0c;但又不知道从何下手&…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...