RPC学习

设计协议

相对于 HTTP 的用处,RPC 更多的是负责应用间的通信,所以性能要求相对更高。但 HTTP 协议的数据包大小相对请求数据本身要大很多,又需要加入很多无用的内容,比如换行符号、回车符等;

还有一个更重要的原因是,HTTP 协议属于无状态协议,客户端无法对请求和响应进行关联,每次请求都需要重新建立连接,响应完成后再关闭连接。因此,对于要求高性能的 RPC 来说,HTTP 协议基本很难满足需求,所以
RPC 会选择设计更紧凑的私有协议。

协议要点:

在协议头里面,我们除了会放协议长度、序列化方式,还会放一些像协议标示、消息 ID、消息类型这样的参数,而协议体一般只放请求接口方法、请求的业务参数值和一些扩展属性。这样一个完整的 RPC 协议大概就出来了,协议头是由一堆固定的长度参数组成,而协议体是根据请求接口和参数构造的,长度属于可变的,具体协议如下图所示:

RPC学习

可扩展:

如果加新参数的话,首先不可以放在协议头,那么放在协议体中可以吗

答案是不可以的

因为协议体中的内容都是要经过序列和反序列化的,如果要获取到你参数的值,就必须把整个协议体里面的数据经过反序列化出来,在某些场景下这样做代价有点高

那就变成协议头(固定部分,扩展部分),协议体

RPC学习

序列化和反序列化

实际上任何一种序列化框架,核心思想就是设计一种序列化协议,将对象的类型、属性类型、属性值一一按照固定的格式写到二进制字节流中来完成序列化,再按照固定的格式一一读出对象的类型、属性类型、属性值,通过这些信息重新创建出一个新的对象,来完成反序列化

常见的序列化方式有:JDK,Json,Hessian,Protobuf序列化方式。

选择序列化方式要考虑的因素

  1. 性能和效率
  2. 空间开销’
  3. 通用性和兼容性
  4. 安全性

RPC学习

首选的还是 Hessian 与 Protobuf,因为他们在性能、时间开销、空间开销、通用性、兼容性和安全性上,都满足了我们的要求。其中 Hessian 在使用上更加方便,在对象的兼容性上更好;Protobuf 则更加高效,通用性上更有优势。

在使用过程中编码需注意那些问题

1.对象要尽量简单,没有太多的依赖关系,属性不要太多,尽量高内聚;
2. 入参对象与返回值对象体积不要太大,更不要传太大的集合;
3. 尽量使用简单的、常用的、开发语言原生的对象,尤其是集合类;
4. 对象不要有复杂的继承关系,最好不要有父子类的情况

IO

零拷贝

取消用户空间和内核空间的拷贝

应用进程的每一次读写可以直接将数据从内核区中取出或者写入,再通过DMA将内核中的数据拷贝到网卡或从网卡拷贝到内核。

所以解决方式就是使用户空间和内核空间的数据都在一个地方存取,那就是虚拟内存。

RPC协议在传输数据过程中,中间可能会拆分成好几个数据包,也可能会合并其他请求的数据包,所以消息都需要有边界。那么一端的机器收到消息之后,就需要对数据包进行处理,根据边界对数据包进行分割和合并,最终获得一条完整的消息。

收到消息后,对数据包的分割和合并,是在用户空间完成,还是在内核空间完成的

Netty 的零拷贝就是为了解决这个问题,在用户空间对数据操作进行优化。

Netty 框架中很多内部的 ChannelHandler 实现类,都是通过 CompositeByteBuf、slice、wrap 操作来处理 TCP 传输中的拆包与粘包问题的。

那么 Netty 解决用户空间与内核空间之间的数据拷贝问题的方法:
Netty 的 ByteBuffer 可以采用 Direct Buffers,使用堆外直接内存进行 Socketd 的读写操作,最终的效果与虚拟内存所实现的效果是一样的。

SPI

设计RPC框架时,为了实现插件化架构,可将功能点抽象成接口,将接口与实现分离,并提供接口的默认实现

利用SPI(服务发现机制),可动态的为接口寻找服务

实现:在Classpath 下的 METAINF/services 目录里创建一个以服务接口命名的文件,这个文件里的内容就是这个接口的具体实现类。

服务发现

还是最终一致性性能更好

Original: https://www.cnblogs.com/zz01/p/16488048.html
Author: 山野村夫01
Title: RPC学习

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621456/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Socket 编码入门

    很多同行朋友大概率学过 socket 通信相关知识, send, recv, listen, connect, accept 等等组合, 变幻 无穷 … 相关的介绍书籍…

    数据库 2023年6月9日
    054
  • 分析了2020年3万多条的微博热搜,我看到了什么

    前言 2020年是艰难的一年,但即使再难,也都过去了。 分析一下2020年的新闻热搜,可以大致了解网民都在关注什么。 微博热搜以娱乐为主,头条的热搜更偏向民生与时事。今天,我们先分…

    数据库 2023年6月16日
    091
  • Linux安装nginx并配置ssl自签证书

    一、下载nginx压缩包:官网下载地址http://nginx.org/download/,点击进入选择合适自己系统的版本,本机已centos安装nginx-1.9.1.tar.g…

    数据库 2023年6月14日
    080
  • rsync

    rsync是什么 rsync特性 1)可以镜像保存整个目录树和文件系统。 2)可以很容易做到保持原来文件的权限、时间、软硬连接等。 3)无需特殊权限即可安装。 4)快速:第一次同步…

    数据库 2023年6月14日
    076
  • MySQL InnoDB 锁的二三事

    近日, 在一个小型项目中, 遇到了一个触及我知识盲区的bug. 项目用的是MySQL 5.7.25, 其中有一张表 config_data, 包含四个字段, id, name, v…

    数据库 2023年6月11日
    0106
  • Java中如何遍历字符串呢?

    字符串是程序开发中我们见的最多的一种数据类型 对字符串的操作,也是我们日常涉及的最多的一种操作方式,那么如何遍历字符串为字符并输出呢? 下面笔者讲述三种操作方式,如下所示 1.直接…

    数据库 2023年6月11日
    049
  • 浅谈GTID及简单测试

    今天简单介绍一下GTID,并有部分相关实验。 GTID相信大家都不陌生,GTID的英文全称为Global Transaction Identifier,在MySQL主从架构中应用广…

    数据库 2023年6月16日
    056
  • SQL 版本号排序

    SQL 语句直接对内容为版本号格式的字段进行排序时,排序效果通常不是最终想要的效果,因为最终需要的效果,是需对版本号里的每一段(通常以小数点分隔)按数值进行排序。 解决这个问题,主…

    数据库 2023年6月16日
    066
  • 小心陷入MySQL索引的坑

    索引可以说是数据库中的一个大心脏了,如果说一个数据库少了索引,那么数据库本身存在的意义就不大了,和普通的文件没什么两样。所以说一个好的索引对数据库系统尤其重要,今天来说说MySQL…

    数据库 2023年6月6日
    086
  • MySQL 事务和锁

    事务概述 当多个用户访问相同的数据时,在更改数据的过程中,其他用户可能会同时发起更改请求,为了确保数据库记录的更新从一种一致性状态更改为另一种一致性状态,需要使用事务处理,它具有以…

    数据库 2023年5月24日
    058
  • Dev-tools使用遇到的小问题

    Dev-tools使用遇到的小问题 间隔长时间后重新打开某网页,提示Failed to load data:No resource with given identifier fo…

    数据库 2023年6月6日
    074
  • Could not initialize class org.apache.maven.plugin.war.util.WebappStructureSerializer

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    数据库 2023年6月6日
    077
  • English words chapter 20220927

    本文来自博客园,作者:ukyo–BlackJesus,转载请注明原文链接:https://www.cnblogs.com/ukzq/p/16736392.html Or…

    数据库 2023年6月11日
    074
  • 永久免费!国产操作系统 Deepin V20 Beta版发布(附安装教程)

    深度操作系统(DEEPIN)是武汉深之度科技有限公司致力于为全球用户提供美观易用、安全可靠的Linux发行版。经过一段时间的测试,这款操作系统的Beta版终于今天和大家见面了。这次…

    数据库 2023年6月9日
    0129
  • media配置及把用户头像从数据库展示到前端

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    数据库 2023年6月14日
    080
  • Java 线程常用操作

    继Java线程生命周期继续学习Java线程其他常用操作 线程的常用操作 设置线程名字:setName() 获取线程名称:getName() 线程唯一Id:getId() // 自定…

    数据库 2023年6月6日
    075
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球