开源源码

(3)深入理解 RPC 之传输篇

2019-06-17  本文已影响17人  hedgehog1112

一、RpcRequest 和 RpcResponse

二、Socket传输

三、Netty 传输

四、同步与异步 阻塞与非阻塞

总结

RPC 被称为“远程过程调用”,会跨越网络,跨越进程,传输层是不可或缺。网络传输名词:TCP、UDP、HTTP,同步 or 异步,阻塞 or 非阻塞,长连接 or 短连接…两种传输层的实现:

Socket:阻塞式的通信,简单实现方式,可了解传输层工作原理及内容

Netty:  非阻塞式,一般 RPC 场景性能好,被很多RPC 框架作为传输层实现方式

一、RpcRequest 和 RpcResponse

传输层传输主要对象,封装请求 id,方法名,方法参数,返回值,异常等 RPC 调用中需要的一系列信息。

二、Socket传输

Server

Client

dis.readInt() 和 dis.read(byte[] bytes) 决定了使用 Socket 通信是阻塞式操作报文头+报文体是常见传输格式,除此之外,特殊字符(空行)也可划分报文结构。用 int(4字节)传递报问题长度,之后传递报文体,复杂通信协议中,报文头除了存储报文体,还有协议名称,版本,心跳标识等。

网络传输中只有字节能够被识别,引入 Serialization 接口完成 RpcRequest 和 RpcResponse字节相互转换

每次 Server 处理 Client 请求都从线程池中取出一个线程来处理请求,这开销对于 Rpc 调用是不能够接受的,Nett网络框架上场

三、Netty 传输

Server 和 ServerHandler

(1)创建、初始化netty服务端的bootstrap对象

(2)初始化通道:解码RPC请求、编码RPC响应、处理RPC请求

(3)关闭RPC服务器

模拟反射调用,写入RPC相应对象,自动关闭连接

Client 和 ClientHandler

 Netty 好处:实现非阻塞式的调用,关键部分都写了注释。上述代码虽然多,和Socket 通信代码大相径庭,大多数都是 Netty 模板代码,启动服务器,配置编解码器等。真正 RPC 封装操作大多集中在 Handler 的 channelRead 方法(负责读取)以及 channel.writeAndFlush 方法(负责写入)中。

 Netty 不能保证返回的字节大小,所以加上 in.readableBytes() < 4 、 in.markReaderIndex() 区分报文头和报文体

四、同步与异步 阻塞与非阻塞

Socket 同步阻塞,Netty 异步非阻塞,其实有点问题。

其实没有必然的联系,大多数使用 Netty 实现的 RPC 调用其实应当是同步非阻塞的(一般 RPC 也支持异步非阻塞)。

4.1同步/异步要看:消息通信机制

同步:调用没有得到结果前,不返回。一旦返回,就得到返回值。调用者主动等待结果

异步:调用发出后,就直接返回,不会立刻得到结果。被调用者通知调用者(通过状态、通知),或通过回调函数处理调用。如果不关心其返回值,可做成异步接口,提升效率

4.2 阻塞/非阻塞摇篮程序在等待调用结果(消息,返回值)时的状态.

阻塞:结果返回之前,当前线程被挂起。调用线程只有在得到结果之后才会返回。

非阻塞:结果返回之前,不会阻塞当前线程

Socket :声明线程池(10个线程),每次请求分配一个,等待客户端传递报文头和报文体的行为都会阻塞该线程

Netty :每次请求通过 Handler方式处理请求(联想 NIO 中 Selector),非阻塞

同步非阻塞比不一定同步阻塞式的通信,没有最好,只有更合适,同步非阻塞适用于 :1.网络连接数量多 2.每个连接的io不频繁 的场景,与 RPC 调用契合成熟RPC 框架的传输层和协议层通常也会提供多种选择应对不同场景

总结

难点:Socket 的理解,Netty 框架掌握。Netty 的学习有一定的门槛,实际需要掌握的知识点其实并不多(仅仅针对 RPC 框架所涉及的知识点而言),推荐《Netty IN ACTION》以及https://waylau.gitbooks.io/netty-4-user-guide/Getting%20Started/Before%20Getting%20Started.html该网站的例子。

参考资料:http://cmsblogs.com/?p=3875

http://javatar.iteye.com/blog/1123915– 梁飞

https://gitee.com/huangyong/rpc– 黄勇

上一篇下一篇

猜你喜欢

热点阅读