Talend作业设计模式和最佳实践:第2部分

作业设计入门

 

作为有经验的Talend开发者,我总是好奇他人如何创建作业。他们是否正确使用各项功能?用到的样式我是否了解,抑或从未见过?想出的解决方案是否独到而精巧?又或者,鉴于画布/组件数据/工作流程本身的抽象性质,接下来是否愁眉不展,不知所措…无论这些问题的答案如何,我觉得使用专门设计的工具都非常重要。为此我们着手研究“作业设计模式”及与之相关的最佳实践。在我看来,即便已了解Talend的所有特性和功能,但是根本需求仍然不变,那就是探索构建作业的最佳方法。

 

从逻辑上讲,“业务用例”是任何Talend作业的关键基本驱动因素。事实上,我在同一工作流程看到各种不同的情况,也看到了各类不同工作流程。这些“用例”大多数从基本前提出发,即最简单的数据集成作业形式是从某个源提取数据并进行处理;在此过程中可能进行转换,最终将其加载到某个目标位置。因而ETL/ELT代码不可或缺,Talend开发者也正致力于此。这一点我们就不再赘述,接下来放宽眼界,扩大探讨面。

 

奠定DI项目成功的三大基础

 

我们都认同圆凳需要三条腿才能站稳,对吧?软件开发也是如此。构建并交付成功的数据集成项目需要三个基本要素:

 

  • 用例 - 明确定义的业务数据/工作流程要求

  • 技术 - 创建、部署和运行解决方案的工具

  • 方法 - 业界公认的行事方式

 

考虑这些要素,加上完善的“开发指南”文档,我们以此为前提展开探讨。

 

扩展基本理论

 

如果说Talend“作业”在“用例”工作流程中包含了技术,那么“作业设计模式”就是构建它们的最佳实践“方法”。我在这些博文中分享的其他内容即便于您没有价值,至少会让您在作业构建方式上保持一致。如果您找到了更好的方法,认为非常有效,那再好不过,不必做出改变。但是,如果您在性能、可重用性和可维护性方面备受困扰,或者需要反复调整代码以适应不断变化的需求,那么这些最佳实践对Talend开发者大有裨益!

 

需要考虑的另外9个最佳实践:

 

软件开发生命周期 (SDLC)

 

亿万富翁马库斯·莱蒙尼斯 (Marcus Lemonis) 在CNBC财经网的“The Profit”(利润)专栏中,将“人员、产品和流程”视为决定任何业务成败的三个关键因素。对此我非常赞同。SDLC流程对于任何软件开发团队都是殊为关键的环节。正确处理非常重要,而忽视则可能导致项目严重受阻,甚至造成灾难性后果。TalendSDLC“最佳实践指南针对Talend开发人员可用的持续集成和部署功能,深入研究相关概念、原则、规范和细节。强烈建议软件开发团队将SDLC最佳实践纳入“开发指南”文档,然后照此实施。

 

管理工作区

 

当您在笔记本电脑/工作站安装Talend Studio时(假设您拥有管理员权限),通常会在本地磁盘驱动器上创建默认的“工作区”目录,并且与许多软件安装一样,此默认位置位于可执行文件所在的目录中。我认为这么做确实不妥。为什么?

 

项目文件(作业和存储库元数据)的本地副本存储在此“工作区”中,如果是通过Talend 管理中心 (TAC) 连接到源代码控制系统(即SVN或GIT),当您打开项目和保存对象时,这些副本也会同步。我认为应将这些文件放在易于查找和管理的位置,最好是在磁盘上的其他位置(或者其他本地盘)。

 

需要说明,在Talend Studio中创建任何连接时都会使用工作区,包括“本地”及“远程”连接,区别在于后者由TAC管理,而前者则不是。对于我们的订阅客户,“远程”连接通常是唯一使用的类型。

 

对于如何组织目录结构,应在“开发指南”文档中予以明确说明,并由整个团队采行,以实现最佳合作和协作。关键是团队要达成共识、培养纪律性并保持一致性。

 

参考项目

 

您是否使用参考项目?是否了解其具体内容?我发现很多客户都不知道这项简单而高效的功能。我们都希望创建可以跨项目共享的可重用、共用或通用代码。我常常看到开发人员打开一个项目,复制代码片段,然后将其粘贴到单独的(有时是同一个)项目或作业中。或者从一个项目中导出对象,然后将它们导入另一个项目。说来惭愧,这两种方式,我之前都实操过。虽然这些方式基本可行,但如果您曾陷入这些过程带来的麻烦中,就能了解其弊端很多,存在很多潜在的维护问题。怎么办?可以有更好的方法,那就是参考项目!这些项目的确让人眼前一亮。

 

如果您用过TAC来创建项目,可能注意到一个名为“参考”的不显眼的复选框。有没有想过这是用来做什么的?其实,如果创建项目时选中该框,使其成为“参考项目”,那么该项目可以“包含”或“链接”到任何其他项目。在“参考项目”中创建的代码随后可用于链接的项目(只读),因而具备高度可重用性。这在创建各类共用对象和共享代码时十分适用。

 

但是,请将这些“参考项目”保持在最低限度;我们建议仅保留1项作为最佳实践,不过在一些有争议的案例中,也可酌情采用2-3项。注意创建“参考项目”过多则可能失去其原本意义,因此须适可而止。谨慎管理非常重要,应在“开发指南”文档中明确说明其用法和规则,并由整个团队采行,以实现最佳合作和协作。

 

对象命名规则

 

命名规则”确实十分重要,开发团队都了解这一点,因此会制定相应的实践。无论Talend对象名称使用的时间、内容及方式如何,取得合理成功的核心仍然是一致性。对Talend对象命名规则,应在“开发指南”文档中予以明确说明,并由整个团队采行,以实现最佳合作和协作。

 

项目存储库

 

使用Talend Studio(基于Eclipse的IDE,即集成开发环境,简言之就是您的作业编辑器)打开项目时,左侧面板代表项目存储库。这是所有项目对象所在的位置。这里有几个非常重要的版块。首先,您必须要了解“作业设计”版块,以便适应可以创建的3种不同类型的作业(即数据集成、批处理和流式传输)。此外,您还需了解和运用以下版块。

 

  • 上下文组 - 不是在内置作业创建上下文变量,而是在存储库中的上下文组中进行创建,并跨作业(以及参考项目中所包含的项目)予以重用;可以实现各个组有效地保持一致;最佳做法是创建对应于不同环境的组:SBX/DEV/TEST/UAT/PROD,其中 DEV 为默认值;删除现有默认上下文;

 

注意我添加了一个上下文变量“SysENVTYPE”,其中包含选定环境中动态可编程性的值。换言之,我在作业中使用此变量来确定运行时当前正在运行的环境,这样就能以编程方式通过条件逻辑更改相应流程。

 

  • 元数据 - 元数据以不同形式呈现,尽可全数利用,包括数据库连接及其表格模式、各类平面文件布局(csvxmljson等),以及始终颇具用处的通用架构,这种架构可用于多种方式,在此不一一列出了,否则这篇博文内容会特别长

  • 文档 - 生成您自己的项目Wiki并将其发布至团队;此功能将生成一套完整的项目相关html文件,可以轻松导航;此版块十分有用,而且仅需几分钟即可搞定

 

建议在“开发指南”文档中为团队添加一些最佳实践,并在团队中坚持使用。可根据需要进行调整,但要让团队中的每个人都参与进来。

 

版本控制(分支和标记)

 

您可能已经注意到,每个作业属性选项卡都有一个设置主要 (M) 和次要 (m) 版本编号方案的位置。此外,您还可以设置自己的创建状态,其中默认的可能状态包括“开发”、“测试”和“生产”。注意:Talend Open Studio (TOS) 等专为单一开发者设计,无法利用SVN/GIT存储库进行合作开发和源代码控制 (SCC)。您需要知道的是,每当碰到这些内部作业属性,都会在本地工作区中创建作业的完整副本,并与SCC系统同步。我见过一些项目,其中的作业副本由十几个内部版本辗转生成。系统会复制该作业的所有副本,导致所有与SCC同步的从属文件迅速增加,项目因此尾大不掉,每次打开和关闭项目时会造成严重的性能问题。如果遇到这种情况,需要先执行导出,然后,重新导入仅最高版本的作业,以便清理工作区。虽然繁琐,但这么做很有必要。

 

因此,在所有付费订阅环境中,版本控制的最佳做法是使用源生SCC分支和标记机制。这始终是管理项目版本发布的最佳方式,因为SCC只对于每个作业保存的增量信息予以维护。这么做可以显著减少特定作业历史记录所需的空间。使用数字、日期或有用的内容来设计版本管理方案,在“开发指南”文档中予以详细说明,而且整个团队都采用该流程(形成一套正确的程序)。

 

内存管理

 

您希望运行作业吗?是否考虑过作业的内存需求?数据流是否要在tMap中处理数百万行和/或众多列和/或多项查找?您是否考虑过当作业在“作业服务器”上运行时,其他作业可能也在同时运行?有没有想过“作业服务器”有多少核心/运存?您是如何配置tMap连接的?“一次性加载”还是“逐行”进行?您的作业是调用子作业,还是由父作业调用,涉及多少级嵌套作业?子作业是否在单独的JVM中运行?如果编写ESB作业,您知道正在创建多少条路由吗?您是否使用并行化(见下文)技术?好吧...这些问题您是否考虑过?有吗?我打赌没有 …

 

默认设置旨在为可配置的设置提供基本值。作业具有若干设置,包括内存的分配。但默认值并非一定正确,事实上也可能存在错误。您的“用例作业设计”、“操作生态系统”和“实时JVM线程计数”决定了使用的内存量,需要对此进行管理。

 

您可以在项目一级或者特定作业中指定JVM内存设置(如上所述):

首选项 > Talend > 运行

 

做到这一点很重要,否则会产生严重后果。内存管理常常被忽视,但是作为一个团队,无论是在开发还是在操作方面,都应当详细记录相应的指导原则并切实遵循。

 

动态SQL语法

 

许多数据库输入组件需要在其“基本设置”选项卡中包含正确的SQL语法。当然,可以直接在tMyDBInput组件中输入语法,这么做同样可行;但也要考虑相应的要求,如果在运行时需要根据作业(或其父作业)控制下的某些缓解逻辑来动态地构建复杂SQL查询,可以通过相当直接的方法来解决这个问题。为SQL查询的基本结构创建“上下文变量”,到达tMyDBInput组件之前在工作流程中进行设置,然后使用上下文变量代替硬编码查询。

 

例如,我在“引用”项目存储库中开发了“上下文组”,称之为“SystemVARS”,其中包含各种有用且可重用的变量。对于动态SQL范式,我定义以下初始化为“null”的“字符串”变量:

 

根据需要在tJava组件中设置这些变量,然后将它们一并拼接到tMyDBInput查询字段中,如下所示:

 

选择” + Context.sqlCOLUMNS + Context.sqlFROM + Context.sqlWHERE

 

请注意,变量值末尾始终包含一个“空格”,以便形成干净的串联。在需要进一步控制的位置,我也利用了“sqlSYNTAX”变量,并有条件地控制串联SQL语法子句的方式,然后直接将Context.sqlSYNTAX放到tMyDBInput查询字段中。大功告成。从数据库主机角度来看,这并非动态SQL,但这是针对您的作业动态生成的SQL!

 

综上所述,记录这条指导原则,以便每个人都能遵循相同的处理方式。

 

并行化选项

 

Talend提供几种支持代码并行化的机制。正确、高效地使用这些机制,并认真考虑对CPU核心和RAM利用率的潜在影响,就能创建高性能作业设计模式。我们来看选项堆栈:

 

  • 执行计划 - 可将多个作业/任务配置为从TAC并行运行

  • 多个工作流程 - 可在共用相同线程的单个作业中启动多个数据流;当它们之间不存在依赖关系时,这可能是罕见用例场景的技巧,我一般避免这么做,而更倾向于创建单独的作业

  • /子作业 - 使用tRunJob组件调用子作业时,您可以选中“使用独立进程运行子作业”复选框,以建立单独的JVM堆/线程来运行子作业;虽然这并非完全意义上的并行化

  • 组件 - tParallelize组件链接多个数据流以供执行;tPartitioner、tDepartitioner、tCollector和tRecollector组件提供对数据流的并行线程数的直接控制

  • 数据库组件 - 大多数数据库输入/输出组件提供高级设置,以在特定SQL语句上启用并行化线程计数;这些可以高效进行,但设置数字过高可能会适得其反;设为2-5是最佳做法

 

可将所有这些并行化方法相互结合使用,按原样嵌套(但建议谨慎行之);应了解您的内存利用率堆栈。要非常清楚作业设计模式的执行流程。请注意,这些并行化选项仅作为高级功能出现在Talend平台产品。从文档中排除并行化指导原则:请务必避免!

 

成功Talend作业的秘诀

 

希望这些作业设计模式最佳实践有助于您想出创建Talend作业的最佳方式。从根本上来说,构建成功的作业有赖于指导原则、纪律性和一致性。只需制定决策,然后遵循即可。在我们将代码绘制到数据/工作流程画布上时,请谨记:

 

行动是通向所有成功的基本要诀。- 巴勃罗·毕加索

 

最后,我准备了一份“宜与忌”准则清单,其中包含我认为构建成功的Talend作业所需的秘诀:

 

- 同时使用tPreJobtPostJob组件

避免组件分类过密,建议在画布上分散排列

合理布置代码,自上而下、从左至右

- 初次编写代码时不必急于求成

- 明确主作业循环并控制退出点

- 不可忽略错误处理技巧

- 广泛而明智地使用上下文组 (DEV/QA/UAT/PROD)

- 请勿创建大量单一作业布局

创建原子作业模块

- 化繁为简,避免复杂

- 随时使用通用模式(值得商榷的例外是单列模式)

- 记得命名对象

- 在适当位置使用小作业(可能只有少数几处)

- 不要过度使用tJavaFlex组件;tJavatJavaRow可能足矣

- 完成后生成/发布项目文档

- 不要跳过运行时内存堆设置步骤

 

结语

 

好,感觉如何,是否满足?希望您仍然意犹未尽,因为后续我计划就这个系列做进一步讲解,再介绍一些“示范用例”。今天的博文丰富了之前的基础理论,并引入了更高一级的概念,敬请您予以考量,希望对您有用。以上仅为抛砖引玉,也欢迎大家畅所欲言,在评论中谈谈自己遵循的一些最佳做法。期待下次再会。

 

更多Talend资讯,敬请关注:

posted @ 2019-06-21 14:11  TalendChina  阅读(779)  评论(0编辑  收藏  举报