用例

Apache Flink因其丰富的功能集而成为开发和运行多种不同类型应用程序的绝佳选择。Flink的功能包括对流和批处理的支持,复杂的状态管理,事件时间处理语义以及状态的恰好一次一致性保证。此外,Flink可以部署在各种资源管理集群(如YARN,Apache Mesos和Kubernetes)上,也可以部署为裸机硬件上的单个群集。Flink配置为高可用性,没有单点故障。Flink已经被证明可以扩展到数千个核心和万亿字节的应用状态,提供高吞吐量和低延迟,并为世界上一些最苛刻的流处理应用程序提供支持。

下面,我们将探讨由Flink提供支持的最常见类型的应用程序,并指出实际示例。

  • 事件驱动的应用
  • 数据分析应用
  • 数据管道应用

事件驱动的应用

什么是事件驱动的应用?

事件驱动的应用程序是一个有状态的应用程序,它从一个或多个事件流中提取事件,并通过触发计算,状态更新或外部操作对传入事件做出响应。

事件驱动的应用程序是传统应用程序设计的演变,具有分离的计算和数据存储层。在传统应用的体系结构中,应用从远程事务数据库中读取数据并将数据持久化到远程事务数据库。

相比之下,事件驱动的应用程序基于有状态流处理应用程序。在这种设计中,数据和计算是共同定位的,这产生了本地(内存或磁盘)数据访问。通过定期将检查点写入远程持久存储来实现容错。下图描绘了传统应用程序体系结构和事件驱动应用程序之间的差异。

事件驱动的应用有哪些优点?

事件驱动的应用程序不是查询远程数据库,而是在本地访问其数据,从而在吞吐量和延迟方面发挥更好的性能。远程持久存储的定期检查点可以异步和递增完成。因此,检查点对常规事件处理的影响非常小。但是,事件驱动的应用程序设计提供的不仅仅是本地数据访问。在分层体系结构中,多个应用程序共享同一数据库是很常见的。因此,需要协调数据库的任何更改,例如由于应用程序更新或扩展服务而更改数据布局。由于每个事件驱动的应用程序都负责自己的数据,因此对数据表示的更改或扩展应用程序需要较少的协调。

Flink如何支持事件驱动的应用?

事件驱动应用程序的限制由流处理器处理时间和状态的程度来定义。Flink的许多杰出功能都围绕着这些概念。Flink提供了一组丰富的状态原语,可以管理非常大的数据量(最多几TB),并且具有恰好一次的一致性保证。此外,Flink支持事件时间,高度可定制的窗口逻辑,以及通过ProcessFunction实现高级业务逻辑提供的细粒度时间控制。此外,Flink还提供了一个用于复杂事件处理(CEP)的库,用于检测数据流中的模式。

但是,Flink针对事件驱动应用程序的突出特点是保存点功能。保存点是一致的状态图像,可用作兼容应用程序的起点。给定保存点,可以更新应用程序或调整其规模,或者可以启动应用程序的多个版本以进行A / B测试。

什么是典型的事件驱动应用?

  • 欺诈识别
  • 异常检测
  • 基于规则的警报
  • 业务流程监控
  • Web应用程序(社交网络)

数据分析应用

什么是数据分析应用?

分析工作从原始数据中提取信息和洞察力。传统上,分析是在有记录事件的有界数据集上作为批查询或应用程序来执行的。为了将最新数据合并到分析结果中,必须将其添加到分析的数据集中,并重新运行查询或应用程序。结果将写入存储系统或作为报告发出。

借助先进的流处理引擎,还可以实时地执行分析。流式查询或应用程序不是读取有限数据集,而是摄取实时事件流,并在消耗事件时不断生成和更新结果。结果要么写入外部数据库,要么保持为内部状态。仪表板应用程序可以从外部数据库读取最新结果或直接查询应用程序的内部状态。

Apache Flink支持流式和批量分析应用程序,如下图所示。

流式分析应用有哪些优势?

与批量分析相比,连续流分析的优势不仅限于因消除定期导入和查询执行而从事件到洞察的低得多的延迟。与批量查询相比,流式查询不必处理输入数据中的人为边界,这些边界是由定期导入和输入的有界性质引起的。

另一方面是更简单的应用程序架构。批量分析管道由若干独立组件组成,以周期性地调度数据提取和查询执行。可靠地操作这样的管道并非易事,因为一个组件的故障会影响管道的后续步骤。相比之下,在像Flink这样的复杂流处理器上运行的流分析应用程序包含从数据摄取到连续结果计算的所有步骤。因此,它可以依赖于引擎的故障恢复机制。

Flink如何支持数据分析应用?

Flink为连续流式传输和批量分析提供了非常好的支持。具体来说,它具有符合ANSI标准的SQL接口,具有用于批处理和流式查询的统一语义。无论是在记录事件的静态数据集上还是在实时事件流上运行,SQL查询都会计算相同的结果。对用户定义函数的丰富支持可确保在SQL查询中执行自定义代码。如果需要更多的自定义逻辑,Flink的DataStream API或DataSet API提供更多的低级控制。此外,Flink的Gelly库为批量数据集上的大规模和高性能图形分析提供算法和构建块。

什么是典型的数据分析应用?

  • 电信网络的质量监控
  • 分析移动应用程序中的产品更新和实验评估
  • 对消费者技术中的实时数据进行特别分析
  • 大规模图分析

数据管道应用

什么是数据管道?

提取 - 转换 - 加载(ETL)是在存储系统之间转换和移动数据的常用方法。通常会定期触发ETL作业,以便将数据从事务数据库系统复制到分析数据库或数据仓库。

数据管道与ETL作业具有相似的用途。它们可以转换和丰富数据,并可以将数据从一个存储系统移动到另一个存储系统 但是,它们以连续流模式运行,而不是周期性地触发。因此,他们能够从连续生成数据的源中读取记录,并以低延迟将其移动到目的地。例如,数据管道可能会监视文件系统目录中的新文件并将其数据写入事件日志。另一个应用程序可能会将事件流实现到数据库,或者逐步构建和优化搜索索引。

下图描述了定期ETL作业和连续数据管道之间的差异。

数据管道有哪些优势?

连续数据流水线优于周期性ETL作业的显著优势是减少了将数据移动到目的地的延迟。此外,数据管道更加通用,可用于更多用例,因为它们能够连续消耗和发送数据。

Flink如何支持数据管道?

Flink的SQL接口(或表API)可以解决许多常见的数据转换或丰富任务,并支持用户定义的函数。通过使用更通用的DataStream API,可以实现具有更高级要求的数据管道。Flink为各种存储系统(如Kafka,Kinesis,Elasticsearch和JDBC数据库系统)提供了丰富的连接器。它还具有连续的文件系统源,用于监视以时间分区方式写入文件的目录和接收器。

什么是典型的数据管道应用?

  • 电子商务中的实时搜索索引构建
  • 电子商务中持续的ETL

参考资料:

[1].https://flink.apache.org/usecases.html

Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink设计为在所有常见的集群环境中运行,以内存速度和任何规模执行计算。

在这里,我们解释了Flink架构的重要方面。

无界和有界数据的处理

任何类型的数据都是作为事件流产生的。信用卡交易,传感器测量,机器日志或网站或移动应用程序上的用户交互,所有这些数据都作为流生成。

数据可以作为无界或有界流处理。

  1. 无界流 有一个开始,但没有定义的结束。它们不会终止并提供其生成的数据。无界流必须持续处理,即必须在摄取事件后立即处理事件。不可能等待所有的输入数据都到达,因为输入是无界的,并且在任何时间点都不会结束。处理无界数据通常要求以特定顺序(例如事件发生的顺序)摄取事件,以便能够推断结果的完整性。

  2. 有界流具有定义的开始和结束。可以在执行任何计算之前,通过摄取所有数据来处理有界流。有界数据集是可以被排序的,因此处理有界流不需要有序摄取。有界流的处理也称为批处理。

Apache Flink擅长处理无界和有界数据集。精确控制时间和状态使Flink的运行时能够在无界流上运行任何类型的应用程序。有界流由算法和数据结构在内部处理,这些算法和数据结构专门针对固定大小的数据集而设计,从而发挥出性能优势。

随处部署应用

Apache Flink是一个分布式系统,需要计算资源才能执行的应用程序。Flink可以与所有常见的集群资源管理器(如Hadoop YARN,Apache Mesos和Kubernetes)集成,但也可以设置为独立的集群运行。

Flink旨在很好地适用于之前列出的每个资源管理器,这是通过特定于资源管理器的部署模式实现的,这些模式允许Flink以其惯用的方式与每个资源管理器进行交互。

部署Flink应用程序时,Flink会根据应用程序配置的并行性自动识别所需资源,并从资源管理器里申请它们。如果发生故障,Flink会通过申请新资源来替换发生故障的容器。所有提交或控制应用程序的通信都是通过REST调用来进行,这简化了Flink在许多环境中的集成。

以任何规模运行应用

Flink旨在以任何规模运行有状态的流应用,应用程序可以并行化为数千个在集群中分布和同时执行的任务。因此,应用程序可以利用几乎无限量的CPU、主内存、磁盘和网络IO。而且,Flink可以轻松维护数据量非常大的应用状态。其异步和增量检查点算法确保对处理的延迟影响最小,同时保证恰好一次状态的一致性。

用户报告了在其生产环境中运行的Flink集群的规模,这样的规模有点令人印象深刻,例如

  • 应用程序每天处理数万亿个事件,
  • 应用程序维护多个TB的状态,以及
  • 应用程序在数千个内核的运行。

内存的性能优势

有状态Flink应用针对本地状态的访问进行了优化。任务状态始终保留在内存中,或者,如果状态大小超过可用内存,则保存在可高效访问的磁盘上的数据结构中。因此,任务通过访问本地(通常是内存中)状态来执行所有计算,从而产生非常低的处理延迟。Flink通过定期并且异步地把本地状态打检查点并持久化到存储设备来保证在出现故障时的恰好一次状态的一致性。

参考资料

[1].https://flink.apache.org/flink-architecture.html

微服务解惑

微服务与容器

微服务又指的是在传统应用架构的基础上,按照业务能力将系统拆分成多个服务,每个服务都是一个独立的应用,对外提供一些列的公共服务API,服务之间以轻量的方式互相调用。
微服务里的每个服务都是一个组件,通过编排组合从而达到独立、解耦、组件化、易维护、可复用、可替换、高可用的设计原则。微服务后,自动化部署以及运维是比较头疼的事,容器技术解决了这个问题。

  • 好的架构需要考虑后面的扩展以及修改
  • 好的架构是解耦的,需改一个地方不会影响另外一个地方
  • 好的架构是轻便灵活的,一个应用最好只解决一个问题,而不是叠加功能

微服务的标签

  • 单一职责
  • 面向服务
  • 自治
  • 易扩展
  • 流程化

微服务的不足

  • 时效性·服务间的调用延时可能导致系统相应慢的问题
  • 一致性·微服务在保证一致性上需要做更多的工作

微服务的价值

  • 资源价值,资源不足是自动扩容,资源过量时自动缩容;
  • 业务价值,工作量、人员数量、交付质量、交付周期;
  • 技术价值,技术是为业务来服务的(个人标注:技术也是业务的一部分而不只是为业务而服务)
  • 用户价值,用户体验好,服务上线快
  • 未来价值,技术不成为业务的瓶颈

微服务的小目标

  • 持续交付
  • 业务敏捷
  • 独立演进
  • 高可用
  • 高性能

微服务的拆与不拆

依据:数据模型、业务模型、关键指标,粒度平衡,边界合理

DevOPS

开发与运维是一个整体,devops是一种思维方式,微服务与devops是天生一对

SpringCloud特点

  • 功能齐全
  • 标准化
  • 简单方便
  • 按需取用
  • 轻量
  • 易扩展、易维护
  • 可复用性

分布式系统组件及操作

配置管理(Spring cloud config)、服务发现/调用(Feign)、断路器、智能路由(ZUUL)、微代理、控制总线、一次性Token、全局锁、决策竞选、分布式会话、集群状态。

注册中心(Eureka)、负载均衡(Ribbon)、断路器(Hystrix)、服务追踪(Sleuth,zipkin)、权限(string security)、接口可视化(Swagger)。

以上内容为《微服务那些事儿》读书笔记。

参考资料

[1]. 微服务那些事儿,纪晓峰著

开篇,马斯克们的Hyperloop

我们先来看张图,下图上部分是现在的高铁,它是跑在露天的轨道上的,下图是Elon Musk’s 在正吹的hyperloop,类似于跑在真空管道里的未来高铁。相比跑在露天轨道里的高铁,跑真空管道里的高铁好处多了:快,节能,安全,比飞机便宜。。。
技术是可以自己进化的,相信类似hyperloop的”高铁+真空管道”的模式就是未来的一种交通出行方式。

hyperloop

那么HYPERLOOP跟本文又有什么关系呢? 是不是有点扯远了?其实本文讲的就是类似给高铁加上真空管道的活,二者本质上是相同的。

管道,Unix/Linux的设计哲学

在Linux或者Unix系统里,有时候我们为了查询某个信息,会输入类似如下的命令行:

1
#cat *.log | grep –v ‘pipeline’ | sort –nr | head –n 10 | tail -5 | awk ‘{print $2}’ | wc –l  > /dev/stdout

这个命令行通过“|”来分隔多个命令,前面命令的输出是紧接着的后面命令的输入,命令之间通过“|”彼此相连,并且一个命令只做一件事情。这里的“|”就是管道,把一个程序的输出和另一个程序的输入连起来的一根管子。

在Unix/Linux里存在这样的管道命令设计哲学:

  • 程序是个过滤器
  • 一个程序只做一件事并且做到最好
  • 一个程序的输入是另外一个程序的输出

下图体现了这样的管道设计哲学,应用之间通过管道相连相互作用:

Uniux/linux pipeline

管道所要解决的问题是:高内聚,低耦合。它以一种“链”的方式将这些程序组合起来,让这些程序组成一条工作流,而每个程序又只作一件事情,给定输入,经过各个程序的先后处理,最终得到输出结果,如下图所示:

Uniux/linux pipeline

Unix/Linux在"每个程序只做一件事并且做好,每个程序的输出是对另一个程序的输入,可组合性"方面是做的非常成功的。但是,UNIX/Linux也存在一些局限性,比如:"仅单机,只支持一对一通信,无容错,仅字节流,数据处理能力有限等"。意思是说 linux/unix的这些管道命令只能在一台机器上跑,没有分布式,并且只能支持一个命令和另外一个命令之间的一对一的输入输出,无法一对多或多对一;无容错,假如管道坏了数据就出错不能恢复;只支持字节流,不支持数据格式的多样性;处理的数据量有限。

因此,我们希望可以找到一个数据处理解决方案,这个方案在保留这些Unix/linux管道的设计哲学优点的同时还能克服其缺点。 幸运的是,我们通过Flink+Pravega打造的第三代“流原生”(stream native)式的大数据处理平台实现了这种设计思想。

流原生,第三代大数据处理平台

下图体现了“流原生”(stream native)式的设计哲学,Flink是“流原生”的计算,Pravega是“流原生”的存储管道,Flink + pravega 是“流原生”的大数据处理平台。数据从pravega管道输入经过map算子计算,输出中间计算结果到pravega的管道里,数据又从pravega的管道里读入到filter算子里,再经过计算,中间结果放到了pravega管道里,再最后的计算结果经过聚合算子的计算放到了目的地的pravega的管道里。这个过程体现了算子编排和管道式编程的设计哲学。在这里pravega起了大数据处理平台里的管道的作用。

Stream processing pipeline

在Unix/Linux中,系统提供管道和命令,用于从一个进程到另一个进程获取字节流。

在“流原生”处理平台上,Flink提供流处理服务,pravega提供流存储服务,数据源自pravega,被Flink算子们处理后输出到pravega,这是一种将事件从一个流处理作业转移到另一个流处理作业的机制。 Flink和Pravega 所遵循的流处理平台设计哲学是:

  • 每个算子都只做一件事,并且做到最好
  • 每个算子的输出是另一个算子的输入
  • 可组合
  • 流式传输:数据是动态的,算子是静态的
  • 算子可编排
  • Pravega是最好的Flink搭档
  • 分布式,扩展到多台机器
  • 可进化的编码/解码

当前的流式处理平台一般是 Flink 加传统的存储类型,这种是”半流原生“式的大数据处理平台,计算是原生的流计算而存储却不是原生的流存储。
而Pravega就是专门给Flink们设计的原生流存储,它的数据传输方式类似于“管道”,不同于传统的块存储,文件存储以及对象存储,它是一个”管道式流存储“。

通过Flink + Pravega的组合可以实现 “流原生”(stream native)式的第三代大数据处理平台,未来已来。。。。。

思考题

最后给大家留个思考题,“流原生”(stream native)的概念有了,Flink + Pravega 也有了,而且二者的代码都是开源的(flink.apache.org, pravega.io),那么怎么把这些开源的东西产品化? 或者这个问题太伤脑筋,我们换个简单的问题:“今天中午吃什么?”

作者简介

常平,毕业于中国科学技术大学,获硕士研究生学历学位,10年+ 存储、布式系统、云计算以及大数据经验,曾就职于Marvell、AMD等,现就职于EMC,资深首席工程师,主要负责流式大数据处理平台的架构设计、编码及产品交付等。

阴阳五行

一说到阴阳五行就容易让人想到大街上的算命先生,然而阴阳五行学说却是中国古代解释世间万物的起源和多样性的哲学理论依据,是中国古代朴素的唯物论和自发的辩证法思想。

中国古代哲学的核心思想之一用“老子”的话来说就是:

“道生一、一生二、二生三、三生万物,万物负阴而抱阳,冲气以为和。”。

而五行学说讲的是:“金 木 水 火 土”这五行,五行相生又相克。木头烧火——木生火;火烧木头成灰——火生土,土长期聚在一起生石头、石头里炼金——土生金,金销水——金生水,水又生土。,水克火,火克金,金克木,木克土,土克水。

但是如下图,五行虽然相生相克但都是为“和”字而服务的,即平衡:

五行

解读开来就是:

“天道生阴阳,阴阳成五行,五行变化成万物,而万物的存在方式和相互关系一直在追求一种“和谐”。“道”在阴阳的相互作用下,产生五行,五行之间相互作用产生世间万物的无穷变化,并且阴阳之间对立消长,五行之间相生相克,自此万物得以和谐发展。借助于阴阳五行的核心要素以及由此而生的非核心要素关系把宇宙看成一个统一的整体,这样的整体:循环平衡、相生相克、有刚有柔、和谐统一

那么这些玄乎的哲学理论跟码农又有什么关系呢?对于本人这么个靠技术混饭吃卖身又卖艺的码农来说,这实在太重要,归纳成一个字就是”和”,对应到技术实现体系里就是一个理念 ”权衡“,英文叫tradeoff“tradeoff”这词实在是太妙了,啥都可以往上套,比如你十一准备到哪旅游啦,中午到哪吃饭啦,买哪里的房子啦,准备追哪个姑娘做老婆啦…….,都需要 tradeoff。技术如此人生又何尝不如是。

分布式系统

通常来讲设计分布式系统的时候需要考虑的最重要的核心要素有五个,这里不是说其他要素就不重要,这是指经过tradeoff过的五个最重要的核心要素,如下图:

分布式系统要素

  1. Capacity,容量,其实这个词翻译成”能力“会更合适,指的是分布式系统里的CPU,内存,硬盘,网络,文件描述符,socket连接数,老板的预期,开发周期,成本预算之类的限制条件,以下所有的要素都受 “容量”的限制,这是前提条件,就比如一辆车最多能跑多快,一个人最多能跳多高都是受自身“容量/能力”的限制的;

  2. Performant, performance + conformant, performant这词也是造的,指的是合适的性能,分布式系统的IOPS,TPS, QPS,Latency,Jitter之类的性能指标要求,性能受限于容量,性能同时又影响了可靠性以及可用性;

  3. Availability,可用性,可用性通常指的是产品或服务在随机时间内调用时处于可服务状态的概率,通常被定义为正常运行时间除以总时间(正常运行时间加停机时间),比如 5个9,6个9,还有个厂家都喜欢的号称的9个9之类的,可用性受容量的限制同时也受可伸缩性的影响,可用性又影响了性能;

  4. Reliability,可靠性,一般指的是出保证不出故障的概率,比如,企业级产品 5个9是保底,可测试性和可维护性通常被定义为可靠性当中的一部分,可伸缩性影响了可靠性,而可靠性又影响了可用性,同时性能又影响了可靠性,可靠性也影响着性能。

  5. Scalability,可伸缩性,这里很容易跟“可扩展性”混淆,可伸缩性可以指的是集群处理越来越多或越来越少的工作的能力,或者是为了适应这种增长或减少而扩大或缩小其能力的能力。可伸缩性影响了可用性,也影响了性能与可靠性,受限于容量。

当然还有另外一些由此而衍生的非核心要素,就不多做详细解释了,比如:

  • Testability,可测试性
  • Security,安全性
  • Observability,可观测性
  • Predictability,可预测性
  • Extensibility,可扩展性
  • Maintainability,可维护性
  • Serviceability, 可服务性

这些非核心要素虽然是非核心但是也不是说就不重要,是开源产品与商业产品差异的关键,关键在如何tradeoff

阴阳五行与分布式系统

将阴阳五行理论与分布式系统设计理论结合起来解读就是:

分布式系统里的“道”就是“产品”,“阴阳“ 就是 ”功能“ 与 “非功能”,五行就是 ”容量、性能、可用性、可伸缩性以及可靠性“,阴阳五行衍生的一些其他关系对应分布式系统五要素衍生的一些其他要素。

用人话来讲就是 开发产品的时候需要考虑功能与非功能两个方面,而要保证产品质量又需要考虑”容量、性能、可用性、可伸缩性以及可靠性“这些核心要素,但是也不能忽略由此而生的一些非核心要素。

那么从这些理论到产品又需要怎么做才能落地呢? 那自然是需要 懂得如何把从这些概念性的、功能的、非功能的、这些核心的、非核心的要素进行设计实现成代码,这就涉及到 “术”的层面了,“道”的层面可以通过看书看论文获得,而“术”的获得除了自身努力还得靠机会,而且每个人的悟性还不一样,这些个”术“以后有空慢慢讲。

思考题

最后给大家留一个思考题: 前面提过老子曰:”道生一、一生二、二生三、三生万物,万物负阴而抱阳,冲气以为和。“, 三之后就是万物,为什么不是 五、不是六、不是七之类的呢?为什么三之后就是万物了?

作者简介

常平,毕业于中国科学技术大学,获硕士研究生学历学位,10年+ 存储、布式系统、云计算以及大数据经验,曾就职于Marvell、AMD等,现就职于EMC,资深首席工程师,主要负责流式大数据处理平台的架构设计、编码及产品交付等。


注:

  1. 这个用五行解释分布式系统的观点,以前在一个业内微信群里提出并且聊过,所以这个解读的方式为本人原创非COPY.
  2. 个人愚钝,悟性有限,欢迎拍砖,砖多了我就拿回去砌墙。

参考资料:

[1]. https://baike.sogou.com/v7556185.htm

本页介绍如何在Kubernetes上部署Flink作业和会话群集。

设置Kubernetes

请参照Kubernetes的设置指南来部署Kubernetes集群。如果您想在本地运行Kubernetes,我们建议使用MiniKube来部署集群。

注意:如果使用MiniKube,请确保minikube ssh 'sudo ip link set docker0 promisc on'在部署Flink群集之前执行。否则,Flink组件无法通过Kubernetes服务自行引用。

Kubernetes上的Flink会话群集

Flink会话群集作为长期运行的Kubernetes部署来执行,请注意,可以在会话群集上运行多个Flink作业。在部署了集群之后,每个作业都需要提交到群集。

一个基本的部署在Kubernetes上的Flink会话群集一般会有三个组件:

  • 一个运行JobManager的deployment或job
  • 一个TaskManagers池 deployment
  • 一个公开JobManager的REST和UI端口的service

在Kubernetes上部署Flink会话群集

使用会话群集的资源定义,采用kubectl命令启动群集:

1
2
3
kubectl create -f jobmanager-service.yaml
kubectl create -f jobmanager-deployment.yaml
kubectl create -f taskmanager-deployment.yaml

然后,您可以通过kubectl proxy按以下方式访问Flink UI :

第一步,保证kubectl proxy在终端中运行

第二步,在浏览器里输入 http://localhost:8001/api/v1/namespaces/default/services/flink-jobmanager:ui/proxy

如果要终止Flink会话群集,可以使用如下命令:

1
2
3
kubectl delete -f jobmanager-deployment.yaml
kubectl delete -f taskmanager-deployment.yaml
kubectl delete -f jobmanager-service.yaml

Kubernetes上的Flink作业集群

Flink作业集群是运行单个作业的专用集群,这项作业是打包在flink镜像里的,因此,不需要提交额外的作业对象,步骤如下:

创建特定于作业的镜像

Flink作业集群镜像需要包含启动集群的作业的用户代码jar。因此,需要为每个作业构建专用的容器镜像。请按照这些说明构建Docker镜像。

在Kubernetes上部署Flink作业集群

要在Kubernetes上部署作业集群,请按照这些说明进行操作。

高级群集部署

GitHub上提供了早期版本的Flink Helm chart

附录

会话群集资源定义

部署使用的最新镜像 flink:latest 可在Docker Hub上找到。该镜像是用这个工具 https://github.com/docker-flink/docker-flink 构建的

jobmanager-deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: flink-jobmanager
spec:
replicas: 1
template:
metadata:
labels:
app: flink
component: jobmanager
spec:
containers:
- name: jobmanager
image: flink:latest
args:
- jobmanager
ports:
- containerPort: 6123
name: rpc
- containerPort: 6124
name: blob
- containerPort: 6125
name: query
- containerPort: 8081
name: ui
env:
- name: JOB_MANAGER_RPC_ADDRESS
value: flink-jobmanager
"

taskmanager-deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: flink-taskmanager
spec:
replicas: 2
template:
metadata:
labels:
app: flink
component: taskmanager
spec:
containers:
- name: taskmanager
image: flink:latest
args:
- taskmanager
ports:
- containerPort: 6121
name: data
- containerPort: 6122
name: rpc
- containerPort: 6125
name: query
env:
- name: JOB_MANAGER_RPC_ADDRESS
value: flink-jobmanager
"

jobmanager-service.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"
apiVersion: v1
kind: Service
metadata:
name: flink-jobmanager
spec:
ports:
- name: rpc
port: 6123
- name: blob
port: 6124
- name: query
port: 6125
- name: ui
port: 8081
selector:
app: flink
component: jobmanager
"

作者标注

经过验证, 到当前版本为止 flink-1.7 snapshot,构建 flink docker镜像需要采用这个flink docker 构建工具 https://github.com/docker-flink/docker-flink,按照flink官方代码库里的构建出来的flink镜像有些功能不能用,比如 flink-standalone模式,report metrics等。

Docker设置

Docker Hub上有关于Apache Flink的Docker镜像,可用于部署flink群集。Flink镜像库还包含用于创建容器映像以部署flink工作集群的一些工具以及说明。

Flink会话群集可用于运行多个业务。在部署后,每个业务都需要提交到集群才能跑起来。

Docker镜像

Flink镜像库托管在docker hub,提供了flink1.2.1以及之后的版本镜像。

注意: Docker镜像是由个人提供的社区项目,它们并不是Apache Flink PMC的官方版本(作者标注:所以需要用这个个人的构建工具,而不是官方代码库里的构建工具)。

Flink作业集群

Flink作业集群是运行单个作业的专用集群,这是镜像内容的一部分,因此,不需要额外的工作。

Docker镜像

Flink作业集群镜像需要包含启动集群的作业的用户代码jar。因此,需要为每个作业构建专用的容器镜像。该flink-container模块包含一个build.sh脚本,可用于创建此类镜像。有关详细信息,请参阅说明。(作者注:这个是官方的构建方式,试过有问题,比如跑 flink-standalone再 report metrics)

Flink与Docker Compose

Docker Compose是一种很方便的用于在本地启动一组Flink Docker容器的方式。

GitHub上提供了集群部署实例作业群集示例的配置文件。

用法

启动集群

$docker-compose up

以deamon的方式启动集群

$docker-compose up -d

集群扩展 N 个 TaskManagers

$docker-compose scale taskmanager=<N>

销毁集群

$docker-compose kill

当拉起一个Flink群集后,您可以访问 http:// localhost:8081的Web UI ,在界面里您还可以将作业提交到群集。

如果要通过命令行将作业提交到会话群集,必须将JAR复制到JobManager容器里并从那里执行作业。

例如:

1
2
3
$ JOBMANAGER_CONTAINER=$(docker ps --filter name=jobmanager --format={{.ID}})
$ docker cp path/to/jar "$JOBMANAGER_CONTAINER":/job.jar
$ docker exec -t -i "$JOBMANAGER_CONTAINER" flink run /job.jar

概述

通常,分布式存储系统以及分布式缓存系统习惯采用分布式哈希(DHT)算法来实现数据的分区分配(路由)以及负载均衡,普通的分布式hash算法通过增添虚拟节点,对物理的热点区间进行划分,将负载分配至其他节点,从而达到负载均衡的状态,但是这并不能保证集群的负载就一定很是的均衡。

而一种改进过的一致性Hash算法,即带边界因子的一致性Hash算法,其严格控制每个节点的负载从而能获得更好的负载均衡效果[1][2]。

普通的DHT算法

假设有8个Object,通过下图的DHT算法:

  1. object 0,1,2映射到了虚拟节点vNode0 : object 0,1,2 –> vNode0
  2. Object 3,4,5 映射到了vNode1:object 3,4,5 –> vNode1
  3. Object 6映射到 vNode2:object 6 –> vNode2
  4. Object 7映射到 vNodeN:object 7 –> vNodeN

distributed-DHT-1

distributed-DHT-2

很明显,Vnode0和vNode1 都落了三个 object,而 vNode2和vNodeN 都只落了 1个Object,这里的DHT算法负债均衡因子并不是很好。

带负载边界因子的DHT算法

假设有8个Object,通过如下图的DHT with bounded loads算法:

distributed-DHT-3

distributed-DHT-4

第一轮映射:

  1. object 0,1,2 需要映射到了虚拟节点vNode0,但是vNode0的权重因子是 2,因此只完成了 object 0,1 –> vNode0, object 2不能映射到节点 vNode0;
  2. Object 3,4,5 需要映射到了虚拟节点vNode1:但是vNode1的权重因子是 2,因此只完成了 object 3,4 –> vNode1, object 5不能映射到节点 vNode1;
  3. Object 6映射到 vNode2:object 6 –> vNode2
  4. Object 7映射到 vNodeN:object 7 –> vNodeN

第二轮映射:

  1. Object 2 映射到 vNode1,但是vNode1权重因子=0, 不能被接收,继续往下一个节点走,发现vNode2 权重因子是2,还剩权重因子1,可以被映射,因此 object 2–>vNode2
  2. Object 5 映射到 vNode2,但是vNode2现在的权重因子=0, 不能被接收,继续往下一个节点走,发现vNodeN 权重因子是2,还剩权重因子1,可以被映射,因此 object 5–>vNodeN

最终的映射结果是:

  1. object 0,1映射到了虚拟节点vNode0 : object 0,1 –> vNode0
  2. Object 3,4 映射到了vNode1:object 3,4 –> vNode1
  3. Object 2,6映射到 vNode2:object 2,6 –> vNode2
  4. Object 5,7映射到 vNodeN:object 5,7 –> vNodeN

很明显,Vnode0,vNode1,vNode2, vNodeN 每个节点都分到2个 object,
显然带负载边界因子的DHT算法负债均衡比普通的DHT算法来的好。

这些节点的负载因子可以从IO,CPU,MEM,Disk,Network等输入因子计算出来。

作者简介

常平,毕业于中国科学技术大学,获硕士研究生学历学位,10年+ 存储、布式系统、云计算以及大数据经验,曾就职于Marvell、AMD等,现就职于EMC,资深首席工程师,主要负责流式大数据处理平台的架构设计、编码及产品交付等。

参考资料

[1] https://research.googleblog.com/2017/04/consistent-hashing-with-bounded-loads.html

[2] https://medium.com/vimeo-engineering-blog/improving-load-balancing-with-a-new-consistent-hashing-algorithm-9f1bd75709ed