消息队列高手课
李玥
美团高级技术专家
52199 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
进阶篇 (21讲)
消息队列高手课
15
15
1.0x
00:00/00:00
登录|注册

32 | 动手实现一个简单的RPC框架(二):通信与序列化

error
code
type
version
requestId
send
ResponseHeader
Header
send
getSerializeClass
type
parse
serialize
size
getSerializeClass
type
parse
serialize
size
serialize
parse
InFlightRequests class
ResponseFuture class
NettyTransport class
Command class
Transport interface
MetadataSerializer
StringSerializer
Serializer interface
SerializeSupport
使用Netty来实现异步网络通信
设计通用的高性能序列化实现
思考题
小结
通信与序列化
动手实现一个简单的RPC框架(二):通信与序列化

该思维导图由 AI 生成,仅供参考

你好,我是李玥。
继续上节课的内容,这节课我们一起来实现这个 RPC 框架的通信和序列化部分。如何实现高性能的异步通信、如何来将结构化的数据序列化成字节流,用于网络传输或者存储到文件中,这两部分内容,我在进阶篇中都有在专门的课程分别讲解过。
网络传输和序列化这两部分的功能相对来说是非常通用并且独立的,在设计的时候,只要能做到比较好的抽象,这两部的实现,它的通用性是非常强的。不仅可以用于我们这个例子中的 RPC 框架中,同样可以直接拿去用于实现消息队列,或者其他需要互相通信的分布式系统中。
我们在实现这两部分的时候,会尽量以开发一个高性能的生产级系统这样的质量要求来设计和实现,但是为了避免代码过于繁杂影响你理解主干流程,我也会做适当的简化,简化的部分我会尽量给出提示。

如何设计一个通用的高性能序列化实现?

我们先来实现序列化和反序列化部分,因为后面讲到的部分会用到序列化和反序列化。
首先我们需要设计一个可扩展的,通用的序列化接口,为了方便使用,我们直接使用静态类的方式来定义这个接口(严格来说这并不是一个接口)。
public class SerializeSupport {
public static <E> E parse(byte [] buffer) {
// ...
}
public static <E> byte [] serialize(E entry) {
// ...
}
}
上面的 parse 方法用于反序列化,serialize 方法用于序列化。如果你对 Java 语言不是特别的熟悉,可能会看不懂<E>是什么意思,这是 Java 语言泛型机制,你可以先忽略它。看一下如何来使用这个类就明白了:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了如何实现一个简单的RPC框架的通信和序列化部分。作者首先介绍了设计通用的高性能序列化实现的方法,通过实现可扩展的、通用的序列化接口,实现了序列化和反序列化的功能。接着,作者详细介绍了如何利用Java的SPI类加载机制将所有的Serializer的实现类加载到SerializeSupport的Map中。最后,作者给出了一个String类型的序列化实现示例,并提到了更复杂的序列化实现MetadataSerializer。 在网络通信部分的实现中,作者介绍了如何使用Netty实现异步网络通信。通过封装通信部分为接口,实现了客户端发送请求、服务端返回响应的功能。在实现中,作者使用了CompletableFuture对象来实现灵活的同步和异步调用。此外,还介绍了通信协议的设计原则,包括协议版本号和持续升级能力的重要性。在实现异步网络传输时,作者还分享了背压机制的实现,以避免客户端请求速度过快导致大量请求失败的问题。 总的来说,本文通过清晰的代码示例和详细的解释,帮助读者了解了如何实现序列化和异步网络通信的关键技术,以及在设计通信协议和实现中需要考虑的重要因素。这些内容对于想要深入了解RPC框架实现的读者来说具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《消息队列高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(22)

  • 最新
  • 精选
  • Switch
    使用fastjson实现,改动代码见:https://gist.github.com/Switch-vov/8cb76aabd1e1addcdbec205cc06d9023

    作者回复: 赞交作业的同学👍

    2019-11-02
    2
    5
  • A9
    老师的课程很多地方让人茅塞顿开,感觉从高中毕业之后就再也没有过这种抽丝剥茧学习知识的感觉了。感谢带来这么好的课程

    作者回复: 感谢,希望你能通过学习有收获,有提高。

    2019-10-08
    5
  • A9
    使用JSON字符串进行序列化,String的序列化保持原样。MetaData和RpcRequest修改了size parse serialize函数 https://gist.github.com/WangYangA9/210ca898525832cba8ddd57ae1ae3d13

    作者回复: 👍👍👍

    2019-10-09
    2
  • Tim Zhang
    有一点不是很理解,为啥typeMap不可以是(type, serializer),通过type获取序列化实现类一步操作,现在看源码是通过type拿到class,再class拿到serializer

    作者回复: 这样保存也是可以的,因为我们用二个map,也就是二对儿kv来保存三种数据(type, class和serializer),必然由一种数据要重复保存一下。 获取序列化实现类的时候,需要拿到class对象的目的是检查一下serializer和class对应的数据类型是否一致。

    2019-10-30
    1
  • L.
    小白问一下,send方法的返回值是怎么到completableFuture对象里的,我没看到赋值操作啊,求解。。。

    作者回复: 这部分代码在:NettyTransport#send 方法中,你可以看一下。

    2020-06-02
    2
  • 拒绝
    有点不理解,Server启动时,向NameService注册接口时,序列化对象是MetadataSerializer?

    作者回复: 是这样的。

    2019-10-18
  • 南山
    动手动手,一定要动手,netty不熟,看起来吃力,但也收获满满,每明白一点都是进步~~~

    作者回复: 是这样的,一定要动手写代码。

    2019-10-10
  • Better me
    ResponseInvocation 这个类是相当于一个回调类的形式吧。“就是根据响应头中的 requestId,去在途请求 inFlightRequest 中查找对应的 ResponseFuture,设置返回值并结束这个 ResponseFuture 就可以了。”这里的设置返回值是指code码形式吗?这里的作用是还需要在返回给服务端确认收到吗?老师有空看看

    作者回复: 这里面的返回值不是状态码,而是RPC调用的返回值,比如我们这个HelloService中,这个返回值就是调用HelloServiceImpl.hello()方法的返回值。

    2019-10-09
    2
  • 每天晒白牙
    今日得到 关键字:背压机制(back pressure) 当客户端同步请求服务端时,客户端需要等待服务端处理完请求并返回响应,在此期间,客户端需要等待,这是一种天然背压机制 那换成异步请求呢? 客户端异步请求服务端时,不会等待服务端处理请求,这样就丧失了同步请求的那种天然背压。 如果服务器处理请求的速度慢于客户端发送请求的速度,就会导致InFlightRequest(在途请求,即还未被服务端处理或响应的请求)越来越多,如果这些在途请求保存在内存中,就可能导致内存飙升,进而引发频繁FGC,之前线上遇到过几次FGC的案例【在公众号:每天晒白牙 中分享过一个vertx-redis-client客户端的案例 https://mp.weixin.qq.com/s/fWsy26VeUvb8yPKON3OTmA,后面也遇到rpc框架中也出现类似的问题】都是因为这些在途请求保存在一个无界队列中,请求得不到处理,导致内存占用过高。 想要避免上面的情况,需要我们主动引入背压机制,即在服务端处理不过来的情况要限制客户端的请求速率,具体的做法应该有很多,我列举几个 1.把无界队列换成有界队列,队列满了就不让添加了 2.在往队列中添加请求的时候获取许可,服务端处理完请求释放许可,如果许可没了就阻塞客户端的请求或返回异常 ——每天晒白牙
    2019-10-10
    2
    27
  • Geek_fd81b3
    纸上得来终觉浅,绝知此事要躬行,真是良心课程,赞。
    2020-04-21
    2
收起评论
显示
设置
留言
22
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部