Flink BLOB架构
Flink中支持的BLOB文件类型
jar包
被user classloader使用的jar包
高负荷RPC消息
1. RPC消息长度超出了akka.framesize的大小
2. 在HA摸式中,利用底层分布式文件系统分发单个高负荷RPC消息,比如: TaskDeploymentDescriptor,给多个接受对象。
3. 失败导致重新部署过程中复用RPC消息
TaskManager的日志文件
为了在web ui上展示taskmanager的日志
按存储特性又分为两类
PERMANENT_BLOB
生命周期和job的生命周期一致,并且是可恢复的。会上传到BlobStore分布式文件系统中。
TRANSIENT_BLOB
生命周期由用户自行管理,并且是不可恢复的。不会上传到BlobStore分布式文件系统中。
架构图

BlobStore
BLOB底层存储,支持多种实现`HDFS`,`S3`,`FTP`等,HA中使用BlobStore进行文件的恢复。
BlobServer
* 提供了基于jobId和BlobKey进行文件上传和下载的方法
* 本地文件系统的读写,基于`<path>/<jobId>/<BlobKey>`目录结构
* HA 分布式文件系统的读写,基于`<path>/<jobId>/<BlobKey>`目录结构
* 负责本地文件系统和分布式文件系统的清理工作
* 先存储到本地文件系统中,然后如果需要的话再存储到分布式文件系统中
* 下载请求优先使用本地文件系统中的文件
* 进行HA恢复中,下载分布式系统中的文件到本地文件系统中
BlobClient
* 基于jobId和BlobKey对BlobServer中的文件进行本地文件缓存
* 本地文件的读写,基于`<path>/<jobId>/<BlobKey>`目录结构
* 优先使用本地文件系统中的文件,然后尝试从HA分布式文件中获取,最后才尝试从BlobServer中下载
* 负责本地文件系统的清理工作
LibraryCacheManager
桥接task的classloader和缓存的库文件,其`registerJob`,`registerTask`会构建并缓存job,task运行需要的classloader
示例解析:standalone模式中的jar包管理
JobManager会创建BlobStore、BlobServer、BlobLibraryCacheManager具体过程见JobManager的createJobManagerComponents方法
try {
blobServer = new BlobServer(configuration, blobStore)
blobServer.start()
instanceManager = new InstanceManager()
scheduler = new FlinkScheduler(ExecutionContext.fromExecutor(futureExecutor))
libraryCacheManager =
new BlobLibraryCacheManager(
blobServer,
ResolveOrder.fromString(classLoaderResolveOrder),
alwaysParentFirstLoaderPatterns)
instanceManager.addInstanceListener(scheduler)
}
TaskManager注册到Jobmanager后会创建BlobCacheService、BlobLibraryCacheManager具体过程见TaskManager的associateWithJobManager方法
try {
val blobcache = new BlobCacheService(
address,
config.getConfiguration(),
highAvailabilityServices.createBlobStore())
blobCache = Option(blobcache)
libraryCacheManager = Some(
new BlobLibraryCacheManager(
blobcache.getPermanentBlobService,
config.getClassLoaderResolveOrder(),
config.getAlwaysParentFirstLoaderPatterns))
}
JobClient在向集群提交job的过程中会调用JobSubmissionClientActor的tryToSubmitJob方法进而调用JobGraph对象的uploadUserJars方法
try {
jobGraph.uploadUserJars(blobServerAddress, clientConfig);
} catch (IOException exception) {
getSelf().tell(
decorateMessage(new JobManagerMessages.JobResultFailure(
new SerializedThrowable(
new JobSubmissionException(
jobGraph.getJobID(),
"Could not upload the jar files to the job manager.",
exception)
)
)),
ActorRef.noSender());
return null;
}
LOG.info("Submit job to the job manager {}.", jobManager.path());
jobManager.tell(
decorateMessage(
new JobManagerMessages.SubmitJob(
jobGraph,
ListeningBehaviour.EXECUTION_RESULT_AND_STATE_CHANGES)),
getSelf());
public void uploadUserJars(
InetSocketAddress blobServerAddress,
Configuration blobClientConfig) throws IOException {
if (!userJars.isEmpty()) {
List<PermanentBlobKey> blobKeys = BlobClient.uploadJarFiles(
blobServerAddress, blobClientConfig, jobID, userJars);
for (PermanentBlobKey blobKey : blobKeys) {
if (!userJarBlobKeys.contains(blobKey)) {
userJarBlobKeys.add(blobKey);
}
}
}
}
然后在JobManager的submitJob方法中会调用BlobLibraryCacheManager的registerJob创建并缓存该job的classloader
try {
libraryCacheManager.registerJob(
jobGraph.getJobID, jobGraph.getUserJarBlobKeys, jobGraph.getClasspaths)
}
catch {
case t: Throwable =>
throw new JobSubmissionException(jobId,
"Cannot set up the user code libraries: " + t.getMessage, t)
}
val userCodeLoader = libraryCacheManager.getClassLoader(jobGraph.getJobID)
TaskManager在执行Task时,首先会调用LibraryCacheManager的registerTask从BlobServer下载相应的jar包并创建classloader
blobService.getPermanentBlobService().registerJob(jobId);
// first of all, get a user-code classloader
// this may involve downloading the job's JAR files and/or classes
LOG.info("Loading JAR files for task {}.", this);
userCodeClassLoader = createUserCodeClassloader();
private ClassLoader createUserCodeClassloader() throws Exception {
long startDownloadTime = System.currentTimeMillis();
// triggers the download of all missing jar files from the job manager
libraryCache.registerTask(jobId, executionId, requiredJarFiles, requiredClasspaths);
LOG.debug("Getting user code class loader for task {} at library cache manager took {} milliseconds",
executionId, System.currentTimeMillis() - startDownloadTime);
ClassLoader userCodeClassLoader = libraryCache.getClassLoader(jobId);
if (userCodeClassLoader == null) {
throw new Exception("No user code classloader available.");
}
return userCodeClassLoader;
}
涉及到的相关配置
| 参数 | 默认值 | 描述 |
|---|---|---|
| high-availability.storageDir | 无 | HA BlobStore根目录 |
| blob.storage.directory | <java.io.tmpdir> | BlobServer 本地文件根目录 |
| blob.fetch.num-concurrent | 50 | BlobServer fetch文件的最大并行度 |
| blob.fetch.backlog | 1000 | 允许最大的排队等待链接数 |
| blob.service.cleanup.interval | 3600 | BlobServer cleanup 线程运行的间隔 |
| blob.fetch.retries | 5 | 从BlobServer下载文件错误重试次数 |
| blob.server.port | 0 | BlobServer端口范围 |
| blob.offload.minsize | 1024 * 1024 | 运行通过BlobServer传递的最小消息大小 |
| classloader.resolve-order | child-first | classloader类加载顺序 |
Flink BLOB架构的更多相关文章
- Flink资料(3)-- Flink一般架构和处理模型
Flink一般架构和处理模型 本文翻译自General Architecture and Process Model ----------------------------------------- ...
- Flink| 运行架构
1. Flink运行时组件 作业管理器(JobManager) 任务管理器(TaskManager) 资源管理器(ResourceManager) 分发器(Dispatcher) 2. 任务提交流程 ...
- Flink架构,源码及debug
序 工作中用Flink做批量和流式处理有段时间了,感觉只看Flink文档是对Flink ProgramRuntime的细节描述不是很多, 程序员还是看代码最简单和有效.所以想写点东西,记录一下,如果能 ...
- flink架构介绍
前言 flink作为基于流的大数据计算引擎,可以说在大数据领域的红人,下面对flink-1.7的架构进行逻辑上的分析并和spark做了一些关键点的对比. 架构 如图1,flink架构分为3个部分,cl ...
- Flink入门(二)——Flink架构介绍
1.基本组件栈 了解Spark的朋友会发现Flink的架构和Spark是非常类似的,在整个软件架构体系中,同样遵循着分层的架构设计理念,在降低系统耦合度的同时,也为上层用户构建Flink应用提供了丰富 ...
- Flink原理(一)——基础架构
Flink系列博客,基于Flink1.6,打算分为三部分:原理.源码.实例以及API使用分析,后期等系列博客完成后再弄一个目录. 该系列博客是我自己学习过程中的一些理解,若有不正确.不准确的地方欢迎大 ...
- 揭秘 Flink 1.9 新架构,Blink Planner 你会用了吗?
本文为 Apache Flink 新版本重大功能特性解读之 Flink SQL 系列文章的开篇,Flink SQL 系列文章由其核心贡献者们分享,涵盖基础知识.实践.调优.内部实现等各个方面,带你由浅 ...
- 开篇 | 揭秘 Flink 1.9 新架构,Blink Planner 你会用了吗?
本文为 Apache Flink 新版本重大功能特性解读之 Flink SQL 系列文章的开篇,Flink SQL 系列文章由其核心贡献者们分享,涵盖基础知识.实践.调优.内部实现等各个方面,带你由浅 ...
- Flink的应用场景和架构
Flink的应用场景 Flink项目的理念就是:Flink是为分布式,高性能,随时可用以及准确的流处理应用程序打造的开源流处理框架.自2019年开源以来,迅速成为大数据实时计算领域炙手可热的技术框架. ...
随机推荐
- zoc license code
点击导航栏上的zoc-about zoc,然后: 点击enter license: 然后输入内容即可: part A: 51698/01027/34713 part B: 00937 还有很多其他 ...
- css自问自答(二)
css自问自答(二) 7.掌握定位的一些属性 position 和 display 属性,以及如何浮动(float)和清除(clear)元素,z-index属性 三个属性控制: position 属性 ...
- 了解python wed 框架
随着人工智能发展,python这门编程语言也渐渐被人们熟知.至于python为什么能AL的时代脱颖而出可以看一下旁边的网址了解一下https://blog.csdn.net/lixingshi/art ...
- 第7章 使用寄存器点亮LED灯—零死角玩转STM32-F429系列
第7章 使用寄存器点亮LED灯 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
- bat取时间间隔
@echo off echo 现在时间是%time:~,%点%time:~,%分%time:~,%秒 ,%%time:~,%%time:~,% pause echo 现在时间是%time:~,%点%t ...
- 【LeetCode43】 Multiply Strings
题目描述: 解题思路: java代码: public class LeetCode43 { public static void main(String[] args) { String num1=& ...
- 苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置
苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置,首先要做好如下的准备: 第一:数据的备份:第二:保证正常的wifi连接:第三:有线的鼠标键盘连接: 具体恢复操作步骤: 步骤一:电脑 ...
- C++ 容器类型成员
类型别名 iterator 此容器类型的迭代类型 const_iterator 可以读取元素,但不能修改元素的迭代器类型 size_type 无符号整数类型,足够保存此种容器类型最大可能容器的大小 ...
- TopJUI | easyui HTML Dialog页面间GET方式数据传递
较容易的方式通过URL内带参数进行数据传递 var url = "apddList.html?c0=" + row.uuid + "&c1=" + ro ...
- Get與Post的區別--總結隨筆
關於Get與Post的區別的文章,在網上太多了:有優點有缺點,今天我給各位大哥做一個總結性的隨筆,還請多多包涵~ 首先是W3School上的答案,請查收: GET在浏览器回退时是无害的,而POST会再 ...