Flink运行时架构

引入

误区:作业资源不够用,加大并行度,加大slot。

flink作业部署时管理员需给定以下参数:

  • 并行度:2
  • slot:1
  • JobManager内存:2G
  • TaskManager内存:2G
    在这里插入图片描述
    上面四个参数有什么关系?

首先要了解JobManager和TaskManager是怎么工作的:

flink作业的提交流程:
作业提交给JobManager后,JobManager将作业图(JobGraph)转化为物理可执行的执行图(ExecutionGraph),同时向ResourceManager申请slots资源,ResourceManager启动足够的TaskManager,JobManager就可以把执行图分发给TaskManager,让TaskManager开始工作。
在这里插入图片描述

Flink运行时架构-四大组件

  • 作业管理器(JobManager)
    管理整个作业
  • 任务管理器(TaskManager)
    真正干活儿的人
  • 资源管理器(ResourceManaget)
    负责协调资源, Flink里最重要的资源就是slot
  • 分发器(Dispatcher)

JobManager

作业提交时的主要工作:
第一步:接收提交的jar包、作业图(JobGraph)、逻辑数据流图
第二步:把作业图(JobGraph)转换为执行图(ExecutionGraph), 执行图是物理层面可以执行的,包含了所有可以并发执行的任务,任务彼此之间的数据传输方式等内容。干活的人(TaskManager)拿到执行图就知道自己该做什么事情了。
第三步:向资源管理器(ResourceManager)申请资源,即TaskManager上的slot,申请到了之后就把执行图分发给TaskManager。
Flink作业执行过程中的主要工作:
负责所有需要中央协调的操作,例如检查点(checkpoints)的协调

TaskManager

作业提交时的主要工作:TaskManager启动之后,会向ResourceManager注册它的slots,并且向JobManager提供slots。

Flink作业执行过程中的主要工作:TaskManager会根据执行图(ExecutionGraph)来执行自己的Task任务,通常Flink作业会在多个TaskManager上运行,一个TaskManager相当于一个JVM进程,每个TaskManager可以包含多个slot,slot是任务执行的最小单元,一个slot相当于一个线程,slot的数量代表了这个TaskManager的最大并发执行能力。TaskManager的不同slot之间,内存是隔离的,cpu不是隔离的,如果该TaskManager为单核的,指定的slot却是3,那么在三个slot的实际执行过程中,会来回切换线程,因此推荐slot的个数为CPU的核数。

ResourceManager

ResourceManager主要负责管理slot,Flink为不同环境和资源管理工具提供了不同的ResourceManager,比如YARN, Mesos, K8s,以及standalone部署。

当 standalone模式时,JobManager过来申请slot的时候,slot不足的话,只能等待slot释放。

当 有外部的资源管理平台的时候,JobManager过来申请slot,slot不足的话,ResourceManager会向资源提供平台发起会话请求资源,当有空闲的节点时,可以启动新的TaskManager用来提供slot。

Dispatcher

Dispatcher服务提供REST接口来接收client的job提交,它负责启动JobManager和提交job,同时运行Web UI。Dispatcher的作用可在下图中体现:

在这里插入图片描述

总结

通常来说, JobManager只有一个,TaskManager才是真正执行任务的,所以在给定内存时,TaskManager会多给一些。

并行度和slot的关系

算子的并行度为2代表这个算子可以由两个线程来并行执行。

并行度的设置方式:
a、Operrator Level(算子层次)
b、Execution Environment Level(执行环境层次)
c、Client Level(客户端层次)
d、System Level(系统层次)

并行度的优先级Operrator Level>Execution Environment Level>Client Level>System Level

final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(3);    //=====================执行环境层次设置并行度==================

DataStream<String> text = [...]
DataStream<Tuple2<String, Integer>> wordCounts = text
    .flatMap(new LineSplitter())
    .keyBy(value -> value.f0)
    .window(TumblingEventTimeWindows.of(Time.seconds(5)))
    .sum(1).setParallelism(5);   //================算子层次设置并行度=================

wordCounts.print();

env.execute("Word Count Example");

./bin/flink run -p 10 ../examples/*WordCount-java*.jar  
#=========================提交作业时设置并行度======================
parallelism.default: 1 
#====================flink-conf.yaml文件中设置并行度====================

假设下面的算子链:Source算子,map算子,keyBy算子的并行度都设置的是2,Sink算子的并行度设置的是1。
在这里插入图片描述
上面4个Task就分成了7个subTask, 但是由于算子链优化,source算子到map算子是forward分区器,map到keyBy是hash分区器,flink会把source算子和map算子合并,最终变成5个subTask,每个subTask都需要一个线程来执行,前面提到过一个slot相当于一个线程,所以这5个subTask需要5个slot 。
在这里插入图片描述
假设有两个TaskManager,每个TaskManager的slot为3:
在这里插入图片描述
但是实际上flink还有一个slot共享原则,共享的前提是它们都来自同一个Job的不同task的subtask,所以上面这个作业实际上只需要2个slot了。
在这里插入图片描述
slot共享的好处:
1.作业算子最大并行度与slot个数保持一致,知道自己作业中算子的最大并行度就知道需要多少个slot了
2.充分利用资源

再回顾刚才的参数配置:

  • 并行度:2
  • slot:1
  • JobManager内存:2G
  • TaskManager内存:2G

并行度为2所以默认需要两个slot,我们设置每个TaskManager的slot为1的话,所以总共需要两个TaskManager。每个TaskManager的内存为2个,相当于总共4G的内存。

以前误以为作业处理慢资源不够用时要同时加大并行度和slot:

  • 并行度:2
  • slot:2
  • JobManager内存:2G
  • TaskManager内存:2G

这样配置的结果就是只开启了一台TaskManager,这台TaskManager内存为2G, 两个slot平分这2G内存,每个slot的内存为1G , 反而导致作业资源更加不够用了。

总结:TaskManager个数 = 并行度 ➗ slot个数 (向上取整)

举例:

  • 并行度:10
  • slot:4

会开启3个TaskManager,一共12个slot,其中有2个slot空闲。

补充知识

TaskManager内存模型

TaskManager的内存模型如下,由参数taskmanager.memory.process.size确定,一共包含五部分:堆内存、堆外内存、直接内存、MetaSpace内存以及JVM Overhead内存。
TaskManager内存调优参考链接
在这里插入图片描述
其中Task Heap,Task Off-Heap和Managed Memory是slot均分的,其他是slot共享的。
Task Heap是每个Task运行时所需的堆内存,使用Java代码new出来的对象说占用的内存都是存放在Heap(堆)内存中,它由JVM垃圾收集器维护。
Task Off-Heap通常为0B,如果在Flink应用的代码中调用了Native的方法,需要用到off-heap内存。
Managed Memory是由Flink直接管理的off-heap内存,它主要用于排序、哈希表、中间结果缓存、RocksDB的backend
在这里插入图片描述

作业提交时Graph的转换

  • 首先是通过API会生成transformations,通过transformations会生成StreamGraph
  • 因为有些节点可以打包放在一起被JobManage安排调度,所以可将StreamGraph的某些StreamNode Chain在一起生成JobGraph,前两步转换都是在客户端完成
  • 最后会将JobGraph转换为ExecutionGraph,相比JobGraph会增加并行度的概念,这一步是在Jobmanager里完成的。
    在这里插入图片描述

数据流图的转化过程参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值