找回密码
 立即注册
查看: 204|回复: 0

RPC(三)

[复制链接]
发表于 2022-5-28 09:46 | 显示全部楼层 |阅读模式
上篇介绍了spring cloud是怎么处理HTTP队首阻塞问题的,HTTP2虽然解决了HTTP队首阻塞,但有时性能不一定比HTTP1的好,问题在于TCP也是有队首阻塞的。
TCP 为提供可靠的传输,实行“顺序控制”或“重发控制”机制。这样一旦出现丢包的情况,这条连接就要灯组重新发包,而HTTP2只有一条连接。那其他请求就得等着了。这个问题得到HTTP3解决了。 HTTP3:甩掉TCP、TLS的包袱,构建效络
之前说过RPC没有行业标准,如果自定义 RPC 协议,需要注意要有什么东西?

1,消息 ID;把TCP连接比作一座桥梁的话,消息ID就是车牌号,发出一辆车去拿货物,能准确的接收到回应。
以 Dubbo 为例,消费者发送请求时,使用 AtomicLong 自增,产生一个 消息 ID。由于 Dubbo 底层 IO 操作是异步的,Dubbo 发送请求之后,需要阻塞等待消费者返回信息。消费者会将消息 ID 保存到 Map 结构中,。为了保证请求响应可以一一对应,这就需要提供者返回的响应信息带上请求者消息 ID。 通过响应的消息 ID,通过上面提到 Map 存储数据,就能找到对应的请求。

2,序列化方式;简单来说就是将消息已大家能读懂的方式打包出去,接收回来。常见的序列化方式有:

JDK 原生序列化
那么 JDK 的序列化过程是怎样完成的呢?我们看下面这张图:


序列化过程就是在读取对象数据的时候,不断加入一些特殊分隔符,这些特殊分隔符用于在反序列化过程中截断用。
    头部数据用来声明序列化协议、序列化版本,用于高低版本向后兼容头部数据用来声明序列化协议、序列化版本,用于高低版本向后兼容对象数据主要包括类名、签名、属性名、属性类型及属性值,当然还有开头结尾等数据,除了属性值属于真正的对象值,其他都是为了反序列化用的元数据存在对象引用、继承的情况下,就是递归遍历“写对象”逻辑

JSON
key-value格式大家应该很熟悉,但用 JSON 进行序列化有这样两个问题,你需要格外注意:
    JSON 进行序列化的额外空间开销比较大,对于大数据量服务这意味着需要巨大的内存和磁盘开销;JSON 没有类型,但像 Java 这种强类型语言,需要通过反射统一解决,所以性能不会太好。

Hessian
相对于 JDK、JSON,由于 Hessian 更加高效,生成的字节数更小,有非常好的兼容性和稳定性,所以 Hessian 更加适合作为 RPC 框架远程通信的序列化协议。
但 Hessian 本身也有问题,官方版本对 Java 里面一些常见对象的类型不支持,比如:
    Linked 系列,LinkedHashMap、LinkedHashSet 等,但是可以通过扩展 CollectionDeserializer 类修复;Locale 类,可以通过扩展 ContextSerializerFactory 类修复;Byte/Short 反序列化的时候变成 Integer。

Protobuf
Protobuf 是 Google 公司内部的混合语言数据标准,是一种轻便、高效的结构化数据存储格式,可以用于结构化数据序列化,支持 Java、Python、C++、Go 等语言。Protobuf 使用的时候需要定义 IDL(Interface description language),然后使用不同语言的 IDL 编译器,生成序列化工具类,它的优点是:
    序列化后体积相比 JSON、Hessian 小很多;IDL 能清晰地描述语义,所以足以帮助并保证应用程序之间的类型不会丢失,无需类似 XML 解析器;序列化反序列化速度很快,不需要通过反射获取类型;消息格式升级和兼容性不错,可以做到向后兼容。

Protobuf 非常高效,但是对于具有反射和动态能力的语言来说,这样用起来很费劲,这一点就不如 Hessian,比如用 Java 的话,这个预编译过程不是必须的,可以考虑使用 Protostuff。
Protostuff 不需要依赖 IDL 文件,可以直接对 Java 领域对象进行反 / 序列化操作,在效率上跟 Protobuf 差不多,生成的二进制格式和 Protobuf 是完全相同的,可以说是一个 Java 版本的 Protobuf 序列化框架。但在使用过程中,我遇到过一些不支持的情况,也同步给你:
    ProtoStuff 不支持单纯的 Map、List 集合对象,需要包在对象里面。

可读性也该有一定考虑。序列化协议可以分为两类:
1.文本类序列化方式,如 xml,json。优点就是可读性好,构造方便,调试也简单。不过缺点也明显,传输体积大,性能差。
2.二进制类学序列化方式,如 Hessian,Protobuf,优点性能好。
查了下,其他序列化方式还有 Thrift,Avro。
总结一下这几个序列化协议。我们首选的还是 Hessian 与 Protobuf,因为他们在性能、时间开销、空间开销、通用性、兼容性和安全性上,都满足了我们的要求。其中 Hessian 在使用上更加方便,在对象的兼容性上更好;Protobuf 则更加高效,通用性上更有优势。
内容来自:极客时间 04 | 网络通信:RPC框架在网络通信上更倾向于哪种网络IO模型?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-28 22:21 , Processed in 0.125716 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表