10 | 网络通信优化之通信协议:如何优化RPC网络通信?
10 | 网络通信优化之通信协议:如何优化RPC网络通信?
讲述:李良
时长14:47大小13.52M
RPC 通信是大型服务框架的核心
什么是 RPC 通信
RMI:JDK 自带的 RPC 通信框架
RMI 的实现原理
RMI 在高并发场景下的性能瓶颈
一个高并发场景下的 RPC 通信优化路径
1. 选择合适的通信协议
2. 使用单一长连接
3. 优化 Socket 通信
4. 量身定做报文格式
5. 编码、解码
6. 调整 Linux 的 TCP 参数设置选项
总结
思考题
赞 15
提建议
精选留言(28)
- 夏天39度2019-06-11老师,能说一下Netty是如何实现串行无锁化完成链路操作吗,怎么做到无锁化的线程切换
作者回复: Netty中,分为Reactor主线程和Reactor从线程,主线程主要用来监听连接事件,从线程主要用来处理监听I/O事件,以及处理读写I/O操作。 一般有其他的业务操作,我们可以在handler中创建线程池来处理。但为了减少上下文切换,我们可以在ChannelPipeline上注册handler事件,例如解码过程。一般Reactor从线程监听到读操作,会立即调用ChannelPipeline的fireChannelRead方法完成读操作,在调用完读操作之后,会检查是否有其他handler,如果有,则直接调用,不会创建新的线程。 这种方式的好处是,不用创建新的线程,在从线程中串行化完成所有的I/O以及业务操作,减少上下文切换;坏处是,给从线程带来了一定的阻塞。
共 2 条评论25 - WL2019-06-11请教老师两个问题: 1. 在RMI的实现原理示意图中客户端的存根和服务端的骨架这两个概念是啥意思, 我感觉不太理解. 2. 在TCP的四次挥手中, 客户端最后的TIME_WAIT状态是不是就是CLOSE的状态, 如果不是那TIME_WAIT状态是在啥时候转换成CLOSE状态的.
作者回复: 我先回答第二个问题。 是的,TIME_WAIT状态就是主动断开方的最后状态了。主动断开连接方之所以是TIME_WAIT状态,是担心被断开方没有收到最后的ACK,这个TIME_WAIT时间内核默认设置是2MSL(报文最大生存时间),被断开方如果超时没有收到ACK,将重新发送FIN,主动断开方收到之后又会重新发送ACK通知,重置TIME_WAIT时间。 正常情况下,当主动断开方的TIME_WAIT状态到达了定时时间后,内核就会关闭该连接。 第一个问题,这块文章中没有过多的介绍,我在这里再叙述下: Stub是client端的远程对象的代理,负责将远程对象上的方法调用转发到实际远程对象实现所在的服务器,我们的程序要通过远程调用,底层一定是套接字的字节传输,要一个对象序列化成为字节码,传输到服务器或者客户端的对端之后,再把该对象反序列化成为对应的对象,Stub承担着底层序列化、数据组装以及协议封装等工作。 Skeleton则是server端的服务对象的代理,负责将接收解析远程调用分派到实际远程对象实现调用。Stub与Skeleton的关系以及操作是对应的关系,只有实现了java.rmi.Remote接口的类或者继承了java.rmi.Remote接口的接口,才能作为Stub与Skeleton之间通信的远程对象,Stub与Skeleton之间的通信使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信,JRMP是专为Java的远程对象制定的协议。Stub和Skeleton之间协作完成客户端与服务器之间的方法调用时的通信。
19 - Stalary2019-06-11老师,如果业务架构已经选择了SpringCloud,该如何优化远程调用呢,目前使用Feign,底层配置了HttpClient,发现qps一直上不去,暂时是对频繁的请求做了本地cache,但是需要订阅更新事件进行刷新
作者回复: 可以尝试扩展其他RPC框架,例如有同学提到的Google的grpc框架,也是基于Netty通信框架实现,基于protobuf实现的序列化。
共 3 条评论14 - n882019-10-25写http是短连接不太严谨
作者回复: 这里纠正下,http1.0版本默认是短链接,而在http1.0以后默认是保持连接的,但只是一个单向的长连接,默认情况下保持60s
共 2 条评论9 - 尔冬橙2019-09-14这个Dubbo阿里可以吹很多年啊共 1 条评论5
- 风轻扬2019-08-13老师。我看到留言中有同学提到http和tcp的对比。http不是建立在tcp的基础上吗?http和tcp的关系应该怎么定义呢?
作者回复: http是基于tcp实现的协议。如果做过Socket编程通信,你会发现两个端之间如果要实现接口通信,除了传输我们需要的请求参数和返回参数之外,我们还需要给通信定义一个协议头,单纯的tcp通信是没有协议头的,而http则是在tcp基础上定义了自己的消息头和序列化方式。http通信协议是一种短连接,也就是说通信完成之后会断开连接。 简而言之,http是tcp的一个上层封装协议,http是基于tcp实现的。
共 2 条评论5 - 晓晨同学2019-08-07有个问题请教一下老师 1.一直不清楚通信协议和序列化协议的区别是什么,两者都是制定报文协议然后传输,感觉序列化协议更具体到业务属性
作者回复: 通信协议是指我们传输信息的协议,包括头协议和包体,头协议中可能包含传输的id、包体大小、序列化方式等等信息,序列化则表示我们传输的包体的载体是什么样的格式,例如是将对象转成json格式还是转成xml格式,再转成二进制进行传输。
3 - nightmare2019-06-13能不能讲一下netty的串行无锁化
作者回复: Netty中,分为Reactor主线程和Reactor从线程,主线程主要用来监听连接事件,从线程主要用来处理监听I/O事件,以及处理读写I/O操作。 一般有其他的业务操作,我们可以在handler中创建线程池来处理。但为了减少上下文切换,我们可以在ChannelPipeline上注册handler事件,例如解码过程。一般Reactor从线程监听到读操作,会立即调用ChannelPipeline的fireChannelRead方法完成读操作,在调用完读操作之后,会检查是否有其他handler,如果有,则直接调用,不会创建新的线程。 这种方式的好处是,不用创建新的线程,在从线程中串行化完成所有的I/O以及业务操作,减少上下文切换;坏处是,给从线程带来了一定的阻塞。
3 - Y丶z2019-06-11老师好,我想问下已经在线上跑的服务,序列化方式是hessian,如果直接换成Protobuf,那么consumer会报错吗?如果报错的话,如何避免这种情况发生呢?
作者回复: 服务端和消费端重启,会走protobuf序列化
4 - 张德2019-07-07还知道JAVA和Python系统之间互相调用的thrift
作者回复: thrift框架也很优秀
2 - 晓杰2019-06-11请问老师,对于大文件的传输,用哪种协议比较好
作者回复: 建议使用hessian协议
3 - 假装自己不胖2019-06-11对于网络编程比较迷茫,请问有没有小白一些的读物或博客推荐一下
作者回复: 这块知识点比较多,建议可以看一些基础书籍,例如Unix网络编程、TCP/IP网络编程,再看看netty实战,就可以进阶Java网络编程了。
2 - Sdylan2019-10-15Spring Clound 的Feigin更多是路由功能,将注解拼接成地址,Spring Cloud主要是整体完备,负载均衡、熔断啥的。2
- 钱2019-09-07课后思考及问题 1:网上常见有关TCP和HTTP的问题,比如: TCP连接的建立详细过程?TCP的连接断开过程? 三次握手建立连接,四次握手断开连接,感觉有些简单啦!如果面试时问到这个问题,老师建议该怎么回答? 另外,还有问一次HTTP请求经过了几次TCP连接,这个如果面试时遇到了,老师又建议该怎么好好的回答?展开
作者回复: 熟悉连接时为什么是三次握手,断开时为什么需要四次握手,以及粘包拆包的问题、解决方案。我理解的一次HTTP请求只有一次TCP连接。
共 2 条评论1 - 电光火石2019-06-111. 老师线上有用过grpc吗,看文档说好像现在还不是特别的稳定? 2. 文中的性能测试,http是否有打开keep alive?走tcp无疑更快,我只想知道用http会慢多少,因为毕竟http更简单。有看过其他的benchmark,在打开keep alive的情况下,性能也还行,不知道老师这个测试是否打开?另外,从测试结果上看,当单次请求数据量很大的时候,http比tcp好像查不了多少是吗? 谢谢!展开
作者回复: grpc目前很多公司在用,在Github中有源码阅读https://github.com/grpc。 对的,没有打开keep alive,如果开启效果会好一些,减少了网络连接。
1 - ZeWe2021-09-07RPC 远程服务调用,是一种通过网络通信调用远程服务的技术。RPC框架底层封装了网络通信,序列化等技术,提供接口包。本地调用接口可以无感透明的访问远程服务,是分布式系统的核心。 如何优化RPC框架,可从网络通信,报文序列化两方面考虑。 网络通信 1)选择合适的通信协议 TCP, UDP等 2)TCP协议下 使用长链接,减少连接资源消耗 3)高效的IO模型 如Netty NIO, 非阻塞io,Reactor线程模型,零拷贝等 4) OS层 TCP参数设置 file-max, keepalive-time等 序列化 1) 简单高效的报文设计 2) 高效序列化框架 编码解码展开1
- 惘 闻2020-12-28老师netty的reactor监听链接事件的主线程,可以认为是IO多路复用里的多路复用器selector吗?
- 放下2020-05-23老师你上面Feign的压测结果都是基于HTTP1.0的短链接吗?如果是HTTP1.1压测效果会不会更好一些
作者回复: 会的,现在都默认使用http1.1版本了,默认是在超时时间内为长连接。
- greekw2019-10-20老师,能讲下netty的rector 线程模型的实例,以及串行无锁化设计的原理
作者回复: 加餐篇中讲到了
- lizhibo2019-09-28老师 我想问的 Dubbo怎么更换成Protobuf 系列化协议?是要扩展Dubbo Serialization 接口吗?另外 Kryo 和 Protobuf 哪个性能高点啊
作者回复: 是的,目前2.7版本已经加入了Protobuf序列化。Kryo和Protobuf 性能非常接近,Kryo序列化后的空间要比Protobuf小一些,但Protobuf序列化与反序列化的时间要优于Kryo。