BasicTypeInfo: 任意Java 基本类型(装箱的)或 String 类型。
BasicArrayTypeInfo: 任意Java基本类型数组(装箱的)或 String 数组。
WritableTypeInfo: 任意 Hadoop Writable 接口的实现类。
TupleTypeInfo: 任意的 Flink Tuple 类型(支持Tuple1 to Tuple25)。Flink tuples 是固定长度固定类型的Java Tuple实现。
CaseClassTypeInfo: 任意的 Scala CaseClass(包括 Scala tuples)。
PojoTypeInfo: 任意的 POJO (Java or Scala),例如,Java对象的所有成员变量,要么是 public 修饰符定义,要么有 getter/setter 方法。
GenericTypeInfo: 任意无法匹配之前几种类型的类。
几个点:
NetWorkBufferPool是在stream中被用得最多的一块
在flink当中,堆外内存的申请主要是使用的ByteBuffer
IOReadableWritable 就是flink当中主要拿来做读写的一个类型,写入DataOutputView
wrap(byte[] array) 这个方法,ByteBuffer和byte[]实际上是共享数据空间的
DataInputOutputSerializerTest
DataOutputSerializer 就是一个DataOutputView, 可以将东西读入然后传到ByteBuffer里面
Segment size就是底层可以保存多少内容, isFreed, isOffHeap
core/api/common/typeInfo 当中承载着一些type相关的信息
io/buffer/NetworkBuffer里面就是实现了一个netty当中的ByteBuf
也像ByteBuf一样有Readindex和WriteIndex
可以想getMemorySegment 获取到里面的segment
recycleBuffer()就是将引用计数减一
setSize() 就是移动writeindex
NetWorkEnviroment有一个registerTask 这个函数, 每个Task都有很多的resultPartition,registerTask会将这些注册到NetworkEnv上面
setupPartition 会从NetworkBufferPool里面获取到一个BufferPool分配到resultPartition上面
NetworkBufferPool 和LocalBufferPool 虽然都是叫 Pool,但实际上并不一样。 前者是一个factory,后者是一个BufferPool,(由provider和 recycler 组成)
NetworkBufferPool
getTotalNumberOfMemorySegments就是获取总的资源池
recycleMemorySegments 释放一定的内存
getNumberOfAvailableMemorySegments
createBufferPool
redistribute实际上在多个地方都会用到, 每个localbufferpool能够返回的就是
poll是从头上拿一个,拿不到返回null
add是加到最后,加不上去会报错
LocalBufferPool 里面的 recycleBuffer 就把segment归还了
LocalBufferPool被实例化时,虽然指定了其所需要的内存段的最小数目,
但是NetworkBufferPool并没有将这些内存段实例分配给它,也就是说不是预先静态分配的,
而是调用方调用requestBuffer方法(来自BufferProvider接口),在内部触发对NetworkBufferPool的实例方法requestMemorySegment的调用进而获取到内存段。
collectBuffers:
for (int i = 0; i < 10; ++i) {
for (BufferPool bp : new BufferPool[] { fixedPool, boundedPool, nonFixedPool }) {
Buffer buffer = bp.requestBuffer();
if (buffer != null) {
assertNotNull(buffer.getMemorySegment());
buffers.add(buffer);
continue collectBuffers;
}
}
}
很骚的写法
SerializationTestType 继承了 IOReadableWritable 这个接口
DataOutputSerializer 是实现了一个DataOutputView这个结构,net里面的serialization是靠这个结构体来做的
DataOutputSerializer 里面实际上是维护了一个数组,将这个数组封到一个ByteBuffer里面。
### 每次 SpanningRecordSerializer 尝试去 serializeRecord 都会先清空 serializationBuffer 和lengthBuffer
lengthBuffer 就是保存第几个元素的长度是多少
dataBuffer 就保存了真实的数据
reset 就是把以上两个都置为0
copyToBufferBuilder 每次将内容写入到 BufferBuilder当中去,前四个字节是长度,后四个字节是真实长度
RecordWriter相比ResultPartitionWriter所处的层面更高,并且它依赖于ResultPartitionWriter。 RecordWriter是写入记录的, 后者就是写入一个Partition
ResultPartition 一个map任务如果产生一个结果,他就是一个resultpartition, 但是可能会被很多个reduce去消费,所以一个resultPartition可能会被分为Sub ResultPartition
每个ResultParttion都有一个LocalBufferPool 。
public void addBufferConsumer(BufferConsumer bufferConsumer, int subpartitionIndex) throws IOException {
checkNotNull(bufferConsumer);
ResultSubpartition subpartition;
try {
checkInProduceState();
subpartition = subpartitions[subpartitionIndex];
}
catch (Exception ex) {
bufferConsumer.close();
throw ex;
}
if (subpartition.add(bufferConsumer)) {
notifyPipelinedConsumers();
}
}
就是把消息通过subpartition发出去之后通过JobManager 通知对端,消息已经发出去了
ResultPartitionManager 会用来管理整个 resultPartition
每个NetworkEnviroment会有一个manager
================================================
ResultPartition 就是实现了ResultPartitionWriter这个接口 public class ResultPartition implements ResultPartitionWriter, BufferPoolOwner
ResultWriter 有一个 copyFromSerializerToTargetChannel 的方法,就是将个buffer 进行序列化后,放到subParttion里面去
ResultSubPartitionView 有一个getNextBuffer这个方法 就是从subPartition中拿取一个segment
这个ResultSubPartitionView就是给InputChannel来调用的
再看到消费端, Task是通过SingleInputGate来消费内容的, getNextBufferOrEvent 是用来获取下一个可以消费的数据的
在开始生成的时候,会判断是local还是remote去生成inputChannel
LocalInputChannel 是最简单的input,可以从jvm中去获取对象
RemoteInputChannel 是可以和远程通信的input
NettyConnectionManager是在NetworkEnvironment里面初始化的,associateWithTaskManagerAndJobManager
什么是Arena?当指定PooledByteBufAllocator来执行ByteBuf分配时,最终的内存分配工作被委托给类PoolArena。
由于Netty通常用于高并发系统,所以各个线程进行内存分配时竞争不可避免,这可能会极大的影响内存分配的效率,
为了缓解高并发时的线程竞争,Netty允许使用者创建多个分配器(Arena)来分离锁,提高内存分配效率。
PartitionRequestClientFactory 是用来和对端建立联系的,
RemoteInputChannel 里面有个 ConnectionManager, 当需要和多个不同的 TaskManager 交互的时候, 需要多个不同的PartitionRequestClient
NettyMessage 就是把消息封装在里面的一个结构
BufferResponse:服务端给出的Buffer响应消息,编号为0;
ErrorResponse:服务端的错误响应消息,编号为1;
客户端的消息有:
PartitionRequest:客户端发起的分区请求,编号为2;
TaskEventRequest:客户端发起的任务事件请求,编号为3;
CancelPartitionRequest:客户端发起的取消分区请求,编号为4;
CloseRequest:客户端发起的关闭请求,编号为5;