Talend作业设计模式和最佳实践:第2部分
作业设计入门
作为有经验的Talend开发者,我总是好奇他人如何创建作业。他们是否正确使用各项功能?用到的样式我是否了解,抑或从未见过?想出的解决方案是否独到而精巧?又或者,鉴于画布/组件数据/工作流程本身的抽象性质,接下来是否愁眉不展,不知所措…无论这些问题的答案如何,我觉得使用专门设计的工具都非常重要。为此我们着手研究“作业设计模式”及与之相关的最佳实践。在我看来,即便已了解Talend的所有特性和功能,但是根本需求仍然不变,那就是探索构建作业的最佳方法。
从逻辑上讲,“业务用例”是任何Talend作业的关键基本驱动因素。事实上,我在同一工作流程看到各种不同的情况,也看到了各类不同工作流程。这些“用例”大多数从基本前提出发,即最简单的数据集成作业形式是从某个源提取数据并进行处理;在此过程中可能进行转换,最终将其加载到某个目标位置。因而ETL/ELT代码不可或缺,Talend开发者也正致力于此。这一点我们就不再赘述,接下来放宽眼界,扩大探讨面。
奠定DI项目成功的三大基础
我们都认同圆凳需要三条腿才能站稳,对吧?软件开发也是如此。构建并交付成功的数据集成项目需要三个基本要素:
-
用例 - 明确定义的业务数据/工作流程要求
-
技术 - 创建、部署和运行解决方案的工具
-
方法 - 业界公认的行事方式
考虑这些要素,加上完善的“开发指南”文档,我们以此为前提展开探讨。
扩展基本理论
如果说Talend“作业”在“用例”工作流程中包含了技术,那么“作业设计模式”就是构建它们的最佳实践“方法”。我在这些博文中分享的其他内容即便于您没有价值,至少会让您在作业构建方式上保持一致。如果您找到了更好的方法,认为非常有效,那再好不过,不必做出改变。但是,如果您在性能、可重用性和可维护性方面备受困扰,或者需要反复调整代码以适应不断变化的需求,那么这些最佳实践对Talend开发者大有裨益!
需要考虑的另外9个最佳实践:
软件开发生命周期 (SDLC)
亿万富翁马库斯·莱蒙尼斯 (Marcus Lemonis) 在CNBC财经网的“The Profit”(利润)专栏中,将“人员、产品和流程”视为决定任何业务成败的三个关键因素。对此我非常赞同。SDLC流程对于任何软件开发团队都是殊为关键的环节。正确处理非常重要,而忽视则可能导致项目严重受阻,甚至造成灾难性后果。Talend的SDLC“最佳实践指南”针对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”,其中包含选定环境中动态可编程性的值。换言之,我在作业中使用此变量来确定运行时当前正在运行的环境,这样就能以编程方式通过条件逻辑更改相应流程。
-
元数据 - 元数据以不同形式呈现,尽可全数利用,包括数据库连接及其表格模式、各类平面文件布局(csv、xml、json等),以及始终颇具用处的通用架构,这种架构可用于多种方式,在此不一一列出了,否则这篇博文内容会特别长
-
文档 - 生成您自己的项目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作业所需的秘诀:
- 同时使用tPreJob和tPostJob组件
- 避免组件分类过密,建议在画布上分散排列
- 合理布置代码,自上而下、从左至右
- 初次编写代码时不必急于求成
- 明确主作业循环并控制退出点
- 不可忽略错误处理技巧
- 广泛而明智地使用上下文组 (DEV/QA/UAT/PROD)
- 请勿创建大量单一作业布局
- 创建原子作业模块
- 化繁为简,避免复杂
- 随时使用通用模式(值得商榷的例外是单列模式)
- 记得命名对象
- 在适当位置使用小作业(可能只有少数几处)
- 不要过度使用tJavaFlex组件;tJava或tJavaRow可能足矣
- 完成后生成/发布项目文档
- 不要跳过运行时内存堆设置步骤
结语
好,感觉如何,是否满足?希望您仍然意犹未尽,因为后续我计划就这个系列做进一步讲解,再介绍一些“示范用例”。今天的博文丰富了之前的基础理论,并引入了更高一级的概念,敬请您予以考量,希望对您有用。以上仅为抛砖引玉,也欢迎大家畅所欲言,在评论中谈谈自己遵循的一些最佳做法。期待下次再会。
更多Talend资讯,敬请关注: