缺点:一个TaskManager执行的一个Task触发反压,该TaskManager和上游TaskManager的Socket就不能传输数据,从而影响到其他Task,也会影响到Barrier的流动,导致作业雪崩。在1.5版本之后,Flink是基于信用值的流量控制和反压的,接收端会给发送端授予一定信用值,发送端一但接受到信用通知,就会在信用值所允许的范围内尽可能多的向接收端发送数据,且附带上发送端的积压量。接收端会依据发送端的积压量信息来计算所有发送端在下一轮的信用值,然后再传递给发送端。优点:精确的在Task粒度控制流量,轻量级且高效。 任务链机制
Flink是将一个Job拆成多Task,Task拆成一个或多个SubTask,然后将SubTask放到TaskManager中的Slot中进行运行。根据并行度的不同,一个算子会有一个或多个SubTask。为了使得程序运行的更快,Flink会将多个SubTask融合到一起放到一个Slot里且在同一线程里运行,这就是Flink中的任务链。而如何判断SubTask是否能在一个任务链里,取决于以下几个条件。
底层源码(1.12.0)StreamingJobGraphGenerator类中createJobGraph->setChaining->createChain->isChainable->isChainableInput
private static boolean isChainableInput(StreamEdge edge, StreamGraph streamGraph) {StreamNode upStreamVertex = streamGraph.getSourceVertex(edge);StreamNode downStreamVertex = streamGraph.getTargetVertex(edge);if (!(upStreamVertex.isSameSlotSharingGroup(downStreamVertex)&& areOperatorsChainable(upStreamVertex, downStreamVertex, streamGraph)&& (edge.getPartitioner() instanceof ForwardPartitioner)&& edge.getShuffleMode() != ShuffleMode.BATCH&& upStreamVertex.getParallelism() == downStreamVertex.getParallelism()&& streamGraph.isChainingEnabled())) {return false;}// check that we do not have a union operation, because unions currently only work// through the network/byte-channel stack.// we check that by testing that each "type" (which means input position) is used only oncefor (StreamEdge inEdge : downStreamVertex.getInEdges()) {if (inEdge != edge && inEdge.getTypeNumber() == edge.getTypeNumber()) {return false;}}return true;}
判断条件:
1)上下游算子实例处于同一个SlotSharingGroup中;
2)下游算子的链接策略(ChainingStrategy)为ALWAYS——既可以与上游链接,也可以与下游链接。我们常见的map()、filter()等都属此类;
3)上游算子的链接策略为HEAD或ALWAYS。HEAD策略表示只能与下游链接,这在正常情况下是Source算子的专属;
4)两个算子间的物理分区逻辑是ForwardPartitioner(Flink DataStream有八种物理分区逻辑);
5)两个算子间的shuffle方式不是批处理模式;
6)上下游算子实例的并行度相同;
7)没有禁用算子链。
Flink中每个算子都会属于一个处理槽共享组,一个处理槽共享组所需要的处理槽数等于它内部算子的最大并行度。不同处理槽共享组内的算子,其任务会交给不同的处理槽进行。所有,一个Flink的Job所需要的处理槽等于每一个处理槽共享组内算子最大并行度相加。
默认情况下,所有算子都属于“default”处理槽共享组。如果一个算子的所有输入都属于同一个处理槽共享组,则此算子会继承这个处理槽共享组。如果一个算子的所有输入都属于不同一个处理槽共享组,则此算子会默认加入“default”这个处理槽共享组。
分区机制就是为了使得每一个subtask知道我的数据将要发往哪一个subtask,Flink一共有8中分区策略(详情可查看源码,idea双击Shift,搜索分区策略名称就可以)。
GlobalPartitioner将数据分发到下游算子第一个subtaskShufferPartitioner
将数据随机发放到下游算子的某一个subtaskBroadcastPartitioner
将数据发放给下游算子的每一个subtaskRebalancePartitioner
将数据以循环的方式发放给下游一个个subtask(第一个数据会随机发放给某一个subtask)。RescalePartitioner
基于上下游并行度。如果上游并行度为2,下游并行度为4,则上游一个subtask对应下游两个subtask,然后把数据循环发送给下游对应的subtask。如果上游并行度为4,下游并行度为2,则上游的两个subtask对应下游的一个subtask,然后把数据发送给下游对应的subtask。ForwardPartitioner
将数据分发到下游算子第一个subtask(此时上游的一个subtask对应下游的一个subtask,上游和下游的并行度之比肯定是1:1,要不然就不是ForwardPartitioner)KeyGroupStreamPartitioner
根据key的分组索引选择相应的subtaskCustomPartitionerWarpper
自定义分区器,实现Partitioner接口,重写partition方法进行自定义分区。