| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> 浅谈RPC的实现原理(一) -> 正文阅读 |
|
[网络协议]浅谈RPC的实现原理(一) |
一、RPC的概念RPC 的全称是 Remote Procedure Call,即远程过程调用。 RPC 是帮助我们屏蔽网络编程细节,实现调用远程方法就跟调用本地(同一个项目中的方法)一样的体验,我们不需要因为这个方法是远程调用就需要编写很多与业务无关的代码。 二、RPC的通信流程2.1、建立连接目前我们RPC通信过程中,建立的连接一般是TCP连接。 TCP 是面向连接的 TCP 提供可靠交付,无差错、不丢失、不重复、并且按序到达 TCP 是面向字节流的,发送时发的是一个流 TCP 是可以提供流量控制和拥塞控制的,既防止对端被压垮,也防止网络被压垮 2.2、数据传输2.2.1、序列化1、为什么要序列化? 网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象。对象是不能直接在网络中传输的,所以我们需要提前把它转成可传输的二进制,这个过程我们一般叫做“序列化” 把二进制的消息体逆向还原成请求对象,这个过程我们称之为“反序列化”。 2、序列化的方式有哪些? JDK 原生序列化:序列化具体的实现是由 ObjectOutputStream 完成的,而反序列化的具体实现是由 ObjectInputStream 完成的。 Hessian:Hessian 是动态类型、二进制、紧凑的,并且可跨语言移植的一种序列化框架。Hessian 协议要比 JDK、JSON 更加紧凑,性能上要比 JDK、JSON 序列化高效很多,而且生成的字节数也更小。 Protobuf:Protobuf 是 Google 公司内部的混合语言数据标准,是一种轻便、高效的结构化数据存储格式,可以用于结构化数据序列化,支持 Java、Python、C++、Go 等语言。Protobuf 使用的时候需要定义 IDL(Interface description language),然后使用不同语言的 IDL 编译器,生成序列化工具类, Protobuf?它的优点是: ①.序列化后体积相比 JSON、Hessian 小很多; ②.IDL 能清晰地描述语义,所以足以帮助并保证应用程序之间的类型不会丢失,无需类似 XML 解析器; ③.序列化反序列化速度很快,不需要通过反射获取类型; ④.消息格式升级和兼容性不错,可以做到向后兼容。 2.2.2、协议1、什么是协议? 网络通信在传输的过程中,就是一堆堆的二进制码,协议就是通信双方的约定。通过协议约定,才能知道每一次的请求是什么样的。 为了避免语义不一致的事情发生,我们就需要在发送请求的时候设定一个约定,然后在收到请求的时候按照这个设定的约定进行数据分割。这个约定语义的表达,就是我们所说的协议。 2、协议的作用是什么呢? ①、我们知道只有二进制才能在网络中传输,所以 RPC 请求在发送到网络中之前,他需要把方法调用的请求参数转成二进制;转成二进制后,写入本地 Socket 中,然后被网卡发送到网络设备中。 ②、在传输过程中,RPC 并不会把请求参数的所有二进制数据整体一下子发送到对端机器上,中间可能会拆分成好几个数据包,也可能会合并其他请求的数据包(合并的前提是同一个 TCP 连接上的数据),至于怎么拆分合并,这其中的细节会涉及到系统参数配置和 TCP 窗口大小。对于服务提供方应用来说,他会从 TCP 通道里面收到很多的二进制数据,那这时候怎么识别出哪些二进制是第一个请求的呢? ③、同理在 RPC 传输数据的时候,为了能准确地“断句”,我们也必须在应用发送请求的数据包里面加入“句号”,这样才能帮我们的接收方应用从数据流里面分割出正确的数据。这个数据包里面的句号就是消息的边界,用于标示请求数据的结束位置。举个具体例子,调用方发送 AB、CD、EF 3 个消息,如果没有边界的话,接收端就可能收到 ABCDEF 或者 ABC、DEF 这样的消息,这就会导致接收的语义跟发送的时候不一致了。 2.3、动态代理Spring AOP中,有jdk动态代理,和cglib动态代理,都是给生成相应的代理,去执行业务逻辑。 rpc调用过程中也是如此,我们调用远程接口,就像调用本地的接口方法一样,调用就可以获取到相应的数据,这里面,rpc帮我们屏蔽掉了底层的实现细节,其实底层是动态代理帮我们处理了很多调用逻辑。 三、服务治理3.1、服务发现服务注册:在服务提供方启动的时候,将对外暴露的接口注册到注册中心之中,注册中心将这个服务节点的 IP 和接口保存下来。 服务订阅:在服务调用方启动的时候,去注册中心查找并订阅服务提供方的 IP,然后缓存到本地,并用于后续的远程调用。 3.2、心跳检测为什么要有心跳检测? 目前我们线上的服务都是集群化部署,所以每次发请求前,RPC 框架会根据路由和负载均衡算法选择一个具体的 IP 地址。为了保证请求成功,我们就需要确保每次选择出来的 IP 对应的连接是健康的。那如何保证选择出来的服务是健康的呢?此时涉及到了服务的心跳检测机制 健康状态:建立连接成功,并且心跳探活也一直成功; 亚健康状态:建立连接成功,但是心跳请求连续失败; 死亡状态:建立连接失败。 定时去调用接口提供方,查看服务提供方是否正常 3.3、负载均衡我们的服务是集群化部署的,调用方调用的时候通过负载均衡,将请求分发给这个集群下的每个服务节点,从而达到多个服务节点共同分担请求压力的目的。 负载均衡主要分为软负载和硬负载,软负载就是在一台或多台服务器上安装负载均衡的软件,如 LVS、Nginx 等,硬负载就是通过硬件设备来实现的负载均衡,如 F5 服务器等。 RPC 负载均衡策略一般包括随机权重、Hash、轮询 RPC负载均衡与WEB负载均衡的区别? 它与 Web 服务的负载均衡的不同之处在于:RPC 框架并不是依赖一个负载均衡设备或者负载均衡服务器来实现负载均衡的,而是由 RPC 框架本身实现的,服务调用者可以自主选择服务节点,发起服务调用。 3.4、路由策略现在我们的服务都是集群化部署的,服务提供方会部署多台机器,调用方在调用的时候,会选择其中一台机器去进行请求。 这时候就会涉及到路由策略,如何去找到这一台机器,去请求 3.5、业务分组为什么要进行服务分组? 如上图所示:图1是未经过服务分组,图2是经过服务分组的,在业务请求量不大的情况下,图1是可以解决问题的,但是某一个业务方的请求量突然增大的时候,会对业务提供方所有的服务造成影响,这时候可能会导致自身服务的负载立刻变高,不仅影响自身集群的服务,还会其他业务方也会产生影响。这时候如果有业务分组就会解决这个问题 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 4:35:15- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |