本文基于 Dubbo 2.6.1 版本,望知悉。
1. 概述
本文接 《精尽 Dubbo 源码分析 —— NIO 服务器(四)之 Exchange 层》 一文,分享 dubbo-remoting-api
模块, buffer
包,Buffer 层。
Buffer 在 NIO 框架中,扮演非常重要的角色,基本每个库都提供了自己的 Buffer 实现,例如:
- Java NIO 的
java.nio.ByteBuffer
- Mina 的
org.apache.mina.core.buffer.IoBuffer
- Netty4 的
io.netty.buffer.ByteBuf
在 dubbo-remoting-api
的 buffer
包中,一方面定义了 ChannelBuffer 和 ChannelBufferFactory 的接口,同时提供了多种默认的实现。整体类图如下:
- 其中,红框部分,是 Netty3 和 Netty4 ,实现的自定义的 ChannelBuffer 和 ChannelBufferFactory 类。
2. ChannelBuffer
com.alibaba.dubbo.remoting.buffer.ChannelBuffer
,实现 Comparable 接口,通道 Buffer 接口。
ChannelBuffer 在接口方法的定义上,主要参考了 Netty 的 ByteBuf 进行设计,所以接口和注释基本一致,本文就不一个一个细讲过去,胖友可以看:
独有的接口方法 #factory()
方法,用于逻辑中,需要创建 ChannelBuffer 的情况。
代码如下:
/**
* Returns the factory which creates a {@link ChannelBuffer} whose type and
* default {@link java.nio.ByteOrder} are same with this buffer.
*/
ChannelBufferFactory factory()
2.1 AbstractChannelBuffer
com.alibaba.dubbo.remoting.buffer.AbstractChannelBuffer
,实现 ChannelBuffer 接口,通道 Buffer 抽象类。
构造方法
/** |
FROM 《netty的ByteBuf》
writerIndex 和 readerIndex这时,writerIndex 为 5,这时如果开始读取,那么这个 writerIndex 可以作为上面ByteBuffer flip 之后的 limit。
实现方法
在 AbstractChannelBuffer 实现的方法,都是重载的方法,真正实质的方法,需要子类来实现。以 #getBytes(...)
方法,举例子:
|
- 方法中调用的
#getBytes(index, ds, dstIndex, length)
方法,并未实现。🙂 为啥呢?实质的方法,涉及到字节数组的实现形式。
2.2 ByteBufferBackedChannelBuffer
com.alibaba.dubbo.remoting.buffer.ByteBufferBackedChannelBuffer
,实现 AbstractChannelBuffer 抽象类,基于 java.nio.ByteBuffer 的 Buffer 实现类。
构造方法
/** |
工厂
|
- 对应的工厂是 DirectChannelBufferFactory 或 HeapChannelBufferFactory 。
实现方法
胖友,自己查看。
2.3 HeapChannelBuffer
com.alibaba.dubbo.remoting.buffer.HeapChannelBuffer
,实现 AbstractChannelBuffer 抽象类,基于字节数组的 Buffer 实现类。
构造方法
/** |
工厂
|
- 对应的工厂是 HeapChannelBufferFactory 。
实现方法
胖友,自己查看。
2.4 DynamicChannelBuffer
com.alibaba.dubbo.remoting.buffer.DynamicChannelBuffer
,实现 AbstractChannelBuffer 抽象类,基于动态的 Buffer 实现类。或者说,基于传入的 ChannelBufferFactory 的 Buffer 实现类。
构造方法
/** |
工厂
|
实现方法
每个方法,直接调用 buffer
对应的方法。
3. ChannelBuffers
com.alibaba.dubbo.remoting.buffer.ChannelBuffers
,Buffer 工具类,提供创建、比较 ChannelBuffer 等公用方法。如下图所示:ChannelBuffers
4. ChannelBufferFactory
com.alibaba.dubbo.remoting.buffer.ChannelBufferFactory
,通道 Buffer 工厂接口。方法如下:
ChannelBuffer getBuffer(int capacity); |
4.1 DirectChannelBufferFactory
com.alibaba.dubbo.remoting.buffer.DirectChannelBufferFactory
,实现 ChannelBufferFactory 接口,创建 DirectChannelBuffer 的工厂。
实现比较简单,代码已经加注释,胖友自己查看。
4.2 HeapChannelBufferFactory
com.alibaba.dubbo.remoting.buffer.HeapChannelBufferFactory
,实现 ChannelBufferFactory 接口,创建 HeapChannelBufferFactory 的工厂。
实现比较简单,代码已经加注释,胖友自己查看。
5. IO
实际 IO 操作,是基于 InputStream 和 OutputStream ,例如我们在前文看到的 Serialization 序列化和反序列化,方法如下:
// ... 省略其他方法 |
所以,我们需要将 ChannelBuffer 进行装饰。
另外,我们在回过头来看看 Codec 和 Codec2 接口,方法如下:
// Codec.java |
一个变化点,就是将 OutputStream 和 InputStream ,替换成了 ChannelBuffer ,更好的以 ChannelBuffer 为核心,与其他框架整合。
5.1 ChannelBufferInputStream
com.alibaba.dubbo.remoting.buffer.ChannelBufferInputStream
,实现 InputStream 接口,代码如下:
public class ChannelBufferInputStream extends InputStream { |
5.2 ChannelBufferOutputStream
com.alibaba.dubbo.remoting.buffer.ChannelBufferOutputStream
,实现 OutputStream 接口,代码如下:
public class ChannelBufferOutputStream extends OutputStream { |
666. 彩蛋
厚着的脸皮,水更一篇。
胖友,可以结合本文,在看看 Dubbo 协议的编解码逻辑。