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

既然有HTTP协议,为什么还要有RPC

既然有HTTP协议,为什么还要有RPC?

从TCP聊起

作为一个程序员,假设我们需要在A电脑的进程发一段数据到B电脑的进程,我们一般会在代码里使用socket进行编程。

这时候,我们可选项一般也就TCP和UDP二选一。TCP可靠,UDP不可靠。除非是马总这种神级程序员(早期QQ大量使用UDP),否则,只要稍微对可靠性有些要求,普通人一般无脑选TCP就对了。

类似下面这样。

fd = socket(AF_INET,SOCK_STREAM,0);

其中SOCK_STREAM,是指使用字节流传输数据,说白了就是TCP协议

在定义了socket之后,我们就可以愉快的对这个socket进行操作,比如用bind()绑定IP端口,用connect()发起建连。

在连接建立之后,我们就可以使用send()发送数据,recv()接收数据。

光这样一个纯裸的TCP连接,就可以做到收发数据了,那是不是就够了?

不行,这么用会有问题。

使用纯裸TCP会有什么问题

八股文常背,TCP是有三个特点,面向连接可靠、基于字节流

这三个特点真的概括的非常精辟,这个八股文我们没白背。

每个特点展开都能聊一篇文章,而今天我们需要关注的是基于字节流这一点。

字节流可以理解为一个双向的通道里流淌的数据,这个数据其实就是我们常说的二进制数据,简单来说就是一大堆 01 串。纯裸TCP收发的这些 01 串之间是没有任何边界的,你根本不知道到哪个地方才算一条完整消息。

正因为这个没有任何边界的特点,所以当我们选择使用TCP发送"夏洛"和"特烦恼"的时候,接收端收到的就是"夏洛特烦恼",这时候接收端没发区分你是想要表达"夏洛"+"特烦恼"还是"夏洛特"+"烦恼"

这就是所谓的粘包问题

说这个的目的是为了告诉大家,纯裸TCP是不能直接拿来用的,你需要在这个基础上加入一些自定义的规则,用于区分消息边界

于是我们会把每条要发送的数据都包装一下,比如加入消息头消息头里写清楚一个完整的包长度是多少,根据这个长度可以继续接收数据,截取出来后它们就是我们真正要传输的消息体

而这里头提到的消息头,还可以放各种东西,比如消息体是否被压缩过和消息体格式之类的,只要上下游都约定好了,互相都认就可以了,这就是所谓的协议。

每个使用TCP的项目都可能会定义一套类似这样的协议解析标准,他们可能有区别,但原理都类似

于是基于TCP,就衍生了非常多的协议,比如HTTP和RPC。

HTTP和RPC

我们回过头来看网络的分层图。

TCP是传输层的协议,而基于TCP造出来的HTTP和各类RPC协议,它们都只是定义了不同消息格式的应用层协议而已。

HTTP协议(Hyper Text Transfer Protocol),又叫做超文本传输协议。我们用的比较多,平时上网在浏览器上敲个网址就能访问网页,这里用到的就是HTTP协议。

RPCRemote Procedure Call),又叫做远程过程调用。它本身并不是一个具体的协议,而是一种调用方式

举个例子,我们平时调用一个本地方法就像下面这样。

 res = localFunc(req)

如果现在这不是个本地方法,而是个远端服务器暴露出来的一个方法remoteFunc,如果我们还能像调用本地方法那样去调用它,这样就可以屏蔽掉一些网络细节,用起来更方便,岂不美哉?

 res = remoteFunc(req)

基于这个思路,大佬们造出了非常多款式的RPC协议,比如比较有名的gRPCthrift

值得注意的是,虽然大部分RPC协议底层使用TCP,但实际上它们不一定非得使用TCP,改用UDP或者HTTP,其实也可以做到类似的功能。

到这里,我们回到文章标题的问题。

既然有HTTP协议,为什么还要有RPC?

其实,TCP70年代出来的协议,而HTTP90年代才开始流行的。而直接使用裸TCP会有问题,可想而知,这中间这么多年有多少自定义的协议,而这里面就有80年代出来的RPC

所以我们该问的不是既然有HTTP协议为什么要有RPC,而是为什么有RPC还要有HTTP协议

那既然有RPC了,为什么还要有HTTP呢?

现在电脑上装的各种联网软件,比如xx管家,xx卫士,它们都作为客户端(client)需要跟服务端(server)建立连接收发消息,此时都会用到应用层协议,在这种client/server (c/s)架构下,它们可以使用自家造的RPC协议,因为它只管连自己公司的服务器就ok了。

但有个软件不同,浏览器(browser),不管是chrome还是IE,它们不仅要能访问自家公司的服务器(server),还需要访问其他公司的网站服务器,因此它们需要有个统一的标准,不然大家没法交流。于是,HTTP就是那个时代用于统一 browser/server (b/s) 的协议。

也就是说在多年以前,HTTP主要用于b/s架构,而RPC更多用于c/s架构。但现在其实已经没分那么清了,b/s和c/s在慢慢融合。很多软件同时支持多端,比如某度云盘,既要支持网页版,还要支持手机端和pc端,如果通信协议都用HTTP的话,那服务器只用同一套就够了。而RPC就开始退居幕后,一般用于公司内部集群里,各个微服务之间的通讯。

那这么说的话,都用HTTP得了,还用什么RPC?

仿佛又回到了文章开头的样子,那这就要从它们之间的区别开始说起。

HTTP和RPC有什么区别

我们来看看RPC和HTTP区别比较明显的几个点。

服务发现

首先要向某个服务器发起请求,你得先建立连接,而建立连接的前提是,你得知道IP地址和端口。这个找到服务对应的IP端口的过程,其实就是服务发现

HTTP中,你知道服务的域名,就可以通过DNS服务去解析得到它背后的IP地址,默认80端口。

RPC的话,就有些区别,一般会有专门的中间服务去保存服务名和IP信息,比如consul或者etcd,甚至是redis。想要访问某个服务,就去这些中间服务去获得IP和端口信息。由于dns也是服务发现的一种,所以也有基于dns去做服务发现的组件,比如CoreDNS

可以看出服务发现这一块,两者是有些区别,但不太能分高低。

底层连接形式

以主流的HTTP1.1协议为例,其默认在建立底层TCP连接之后会一直保持这个连接(keep alive),之后的请求和响应都会复用这条连接。

RPC协议,也跟HTTP类似,也是通过建立TCP长链接进行数据交互,但不同的地方在于,RPC协议一般还会再建个连接池,在请求量大的时候,建立多条连接放在池内,要发数据的时候就从池里取一条连接出来,用完放回去,下次再复用,可以说非常环保。

由于连接池有利于提升网络请求性能,所以不少编程语言的网络库里都会给HTTP加个连接池,比如go就是这么干的。

可以看出这一块两者也没太大区别,所以也不是关键。

传输的内容

基于TCP传输的消息,说到底,无非都是消息头header和消息体body。

header是用于标记一些特殊信息,其中最重要的是消息体长度

body则是放我们真正需要传输的内容,而这些内容只能是二进制01串,毕竟计算机只认识这玩意。所以TCP传字符串和数字都问题不大,因为字符串可以转成编码再变成01串,而数字本身也能直接转为二进制。但结构体呢,我们得想个办法将它也转为二进制01串,这样的方案现在也有很多现成的,比如json,protobuf。

这个将结构体转为二进制数组的过程就叫序列化,反过来将二进制数组复原成结构体的过程叫反序列化

对于主流的HTTP1.1,虽然它现在叫超文本协议,支持音频视频,但HTTP设计初是用于做网页文本展示的,所以它传的内容以字符串为主。header和body都是如此。在body这块,它使用json序列化结构体数据。

我们可以随便截个图直观看下。

可以看到这里面的内容非常多的冗余,显得非常啰嗦。最明显的,像header里的那些信息,其实如果我们约定好头部的第几位是content-type,就不需要每次都真的把"content-type"这个字段都传过来,类似的情况其实在body的json结构里也特别明显。

而RPC,因为它定制化程度更高,可以采用体积更小的protobuf或其他序列化协议去保存结构体数据,同时也不需要像HTTP那样考虑各种浏览器行为,比如302重定向跳转啥的。因此性能也会更好一些,这也是在公司内部微服务中抛弃HTTP,选择使用RPC的最主要原因。

HTTP原理

RPC原理

当然上面说的HTTP,其实特指的是现在主流使用的HTTP1.1HTTP2在前者的基础上做了很多改进,所以性能可能比很多RPC协议还要好,甚至连gRPC底层都直接用的HTTP2

那么问题又来了。

为什么既然有了HTTP2,还要有RPC协议?

这个是由于HTTP2是2015年出来的。那时候很多公司内部的RPC协议都已经跑了好些年了,基于历史原因,一般也没必要去换了。

总结

  • 纯裸TCP是能收发数据,但它是个无边界的数据流,上层需要定义消息格式用于定义消息边界。于是就有了各种协议,HTTP和各类RPC协议就是在TCP之上定义的应用层协议。

  • RPC本质上不算是协议,而是一种调用方式,而像gRPC和thrift这样的具体实现,才是协议,它们是实现了RPC调用的协议。目的是希望程序员能像调用本地方法那样去调用远端的服务方法。同时RPC有很多种实现方式,不一定非得基于TCP协议

  • 从发展历史来说,HTTP主要用于b/s架构,而RPC更多用于c/s架构。但现在其实已经没分那么清了,b/s和c/s在慢慢融合。很多软件同时支持多端,所以对外一般用HTTP协议,而内部集群的微服务之间则采用RPC协议进行通讯。

  • RPC其实比HTTP出现的要早,且比目前主流的HTTP1.1性能要更好,所以大部分公司内部都还在使用RPC。

  • HTTP2.0HTTP1.1的基础上做了优化,性能可能比很多RPC协议都要好,但由于是这几年才出来的,所以也不太可能取代掉RPC。

相关文章:

既然有HTTP协议,为什么还要有RPC

既然有HTTP协议,为什么还要有RPC? 从TCP聊起 作为一个程序员,假设我们需要在A电脑的进程发一段数据到B电脑的进程,我们一般会在代码里使用socket进行编程。 这时候,我们可选项一般也就TCP和UDP二选一。TCP可靠&…...

【新2023】华为OD机试 - 选座位(Python)

华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 选座位 题目 疫情期间需要大家保证一定的社交距离 公司组织开交流会议,座位有一排共N个座位 编号分别为[0...n-1] 要求员工一个接着一个进入会议室 并且还可以在任何时候离开会议室 每当一个员工进入时…...

数据分析与SAS学习笔记4

INPUT语句:格式修饰符: “:” 修饰符。表示从下一个非空格列读入数据,直到:1 遇到再下一个空格列; 2 读到预先定义的变量长度; 3 数据行结束。哪个先出现就在哪儿结束。 “&” 修饰符。表示从下一个非空格列读入…...

Xepor:一款针对逆向工程和安全分析的Web路由框架

关于Xepor Xepor是一款专为逆向分析工程师和安全研究专家设计的Web路由框架,该工具可以为研究人员提供类似Flask API的功能,支持以人类友好的方式拦截和修改HTTP请求或HTTP响应信息。 该项目需要与mitmproxy一起结合使用,用户可以使用Xepor…...

Hadoop核心组成和生态系统简介

一、Hadoop的概念 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。Hadoop实现了一个分布式文件系统( Distributed File System)&am…...

Flutter-Charts_painter大数据量绘制性能优化-数据收敛

Flutter-Charts_painter大数据量绘制性能优化-数据收敛 1、背景介绍 HRV测量仪器上传的数据,每秒有250个数据,业务上需要测量180秒,预计有3w-5w个数据点需要绘制到折线图上去。Charts_painter绘制这么大的数据是时候会有些卡顿,…...

使用 GeForce Experience 更新 NVIDIA GPU 显卡驱动

使用 GeForce Experience 更新 NVIDIA GPU 显卡驱动1. NVIDIA GeForce Experience 2. 驱动程序 -> 检查更新文件 3. 下载 如果有可用的新版驱动的话,点击后方的 [下载] 按钮即可。 4. 安装 [快速安装] 按照默认设置安装驱动,[自定义安装] 可以自行…...

Java泛型的<? super T>,<? extend T>的区别

&#xff1f; extends T ? extends T 描述了通配符上界, 即具体的泛型参数需要满足条件: 泛型参数必须是 T 类型或它的子类, 例如: List<? extends Number> numberArray new ArrayList<Number>(); // Number 是 Number 类型的 List<? extends Number>…...

如何做出好看的Excel可视化图表?

可视化死磕excel是不行的&#xff0c;作为数据分析行业的偷懒大户&#xff0c;分享一些我在可视化工具上的使用心得&#xff0c;总结了三大类&#xff1a;快速出图类、专业图表类、高端大屏类。个人经验&#xff0c;大家按需采纳&#xff1a; 一、快速出图类 如果你只是因为偶…...

智能吸吹一体式方案设计特点

一、家用吸吹一体吸尘器方案研发设计要素&#xff1a; 1.小巧的机身设计&#xff0c;一手掌握&#xff0c;无论是床底、沙发下还是家具缝隙之中都能够使用。 2.无线&#xff0c;插电两用&#xff0c;在家方便可插电使用。内置可充电锂电池&#xff0c;充满电也可无线使用。 3.采…...

CSDN 编辑器 Marddown 语法备忘

原文链接&#xff1a;https://blog.csdn.net/blogdevteam/article/details/103478461 本文对其二次加工&#xff0c;增加渲染样式、补充例程、添加未收录的常用语法。 CSDN Markdown 编辑器遵循 CommonMark spec 语法规范。 快捷键 撤销&#xff1a;Ctrl/Command Z 重做&…...

回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测

回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测 目录回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 Matlab实现NGO-BiLSTM北方苍鹰算法…...

Linux——操作系统安装

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。个人爱好: 编程&#xff0c;打篮球&#xff0c;计算机知识个人名言&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石…...

AFLNET lightftp项目报错解决方法

在学习AFLNET的时候&#xff0c;本人尝试对示例项目中的lightftp进行fuzz,而后出现如下报错&#xff1a; AFLNet - the states hashtable should always contain an entry of the initial state 在github项目issue里看到了有人的问题和我一摸一样&#xff0c;Stack Overflow里…...

av 146 003

121. 团队章程的目标是什么? A. 使团队正规化&#xff0c;以便能够清楚地了解资源分配和参与情况 B. 创造一个团队可以自我管理和自我指导的环境 C. 创造一个环境&#xff0c;使团队成员能够尽其所能地工作 D. 创造一种团队归属感&#xff0c;促进包容性和协作性的行为 12…...

干了1年“点点点”,自己辞职了,下一步是继续干测试还是转开发?

最后后台有个粉丝向我吐槽&#xff0c;不知道怎么选择了....下面就他的情况说说怎么选择&#xff1f; 目前已经提桶跑路&#xff0c;在大工厂里混了半年初级低级功能测试经验&#xff0c;并没有什么用。测试培训班来的。从破山村贫困户贫困专项出去的&#xff0c;学校上海的。…...

国产技术迎来突破,14nm芯片横空出世,低代码也有好消息

芯片&#xff0c;被称为工业时代的“粮食”&#xff0c;小到手机手环&#xff0c;大到飞机轮船&#xff0c;几乎各个行业都不离开芯片的支持&#xff0c;其重要性不言而喻。而我国在这一领域一直较为薄弱。 一、“芯片之路坎坷” 由于国内半导体芯片市场底子薄弱、没有主动权…...

使用clickhouse-backup工具备份clickhouse数据库

工具官网&#xff1a;https://github.com/AlexAkulov/clickhouse-backup/dockerhub工具官网&#xff1a;https://hub.docker.com/r/alexakulov/clickhouse-backup注意&#xff1a;这个工具只支持MergeTree 系列表引擎一、clickhouse在容器外的备份和恢复若clickhouse装在容器外…...

python cartopy绘制扇形区域图/cartopy绘制北极部分区域

问题 当绘图时&#xff0c;往往并不需要绘制整块区域&#xff0c;而是想聚焦于局部地区&#xff0c;此时我们需要绘制扇形图。 在cartopy中&#xff0c;只提供普通正方形的框架&#xff0c;如果我们需要其他&#xff0c;边界&#xff0c;需要自己去绘制&#xff0c;最常见的是…...

如何设置股票接口版交易软件的指标涨跌家数?

如何设置股票接口版交易软件指标涨跌家数&#xff1f;今天小编就以通达信为例给大家介绍一下&#xff0c;很多人其实不知道通达信里面有个很厉害的股票情绪的指标&#xff0c;叫做通达信涨跌家数&#xff0c;打开在通达信软件k线界面&#xff0c;然后输入880005就可以找到了。下…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

VisualXML全新升级 | 新增数据库编辑功能

VisualXML是一个功能强大的网络总线设计工具&#xff0c;专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑&#xff08;如DBC、LDF、ARXML、HEX等&#xff09;&#xff0c;并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...