最近,谷歌推出了Google Cloud工作流的测试版。这引起了我的注意,因为我在AWS步骤函数(也是一项工作流服务)上做了很多工作。如果您是少数关心云中工作流的人之一,那么它们之间的区别就非常有趣。对于其他78亿人中的那些人来说,继续前进,这里没有什么可看的。
背景·谷歌的发布似乎有点低调。产品经理菲利普·纳皮克(Filip Knapik)在8月27日发布了一条推文,但真正的“公告”显然是谷歌云中的无服务器工作流(Serverless Workflow),这也是由克纳皮克制作的一段16分钟的YouTube演示。好。
推特上有人说很高兴看到GCP的“Step Functions/Logic Apps”!我觉得这很公平。我不知道Logic Apps是什么时候发布的,但Step Functions是在Re:Invent2016,所以已经有了四年的开发时间。
我将不讨论Logic Apps,为简洁起见,对于AWS步骤功能和Google Cloud工作流,我将仅使用“AWS”和“GCP”。
对于GCP,我依赖于语法参考,并且发现Knapik的YouTube也很有用。对于AWS,我认为最好的起点是Amazon States语言规范。
这篇文章的其余部分强调了这些产品的相似之处和不同之处,并对我的观点进行了自由调味。
YAML vs JSON·AWS用JSON编写工作流(它称之为“状态机”)。GCP使用YAML。Well…。嗯。很多人更喜欢YAML;它更容易编写。老实说,我总是认为JSON状态机是某种汇编级的,并假设有人会想出一种更高级别的方式来表达它们,然后向下编译成JSON。但这种情况并没有太多发生。
我对yaml有一个主要的心理障碍,因为与json或xml不同的是,它没有结束标记,所以如果yaml被截断,无论是由于网络痉挛还是您自己的胖手指,它仍然可能不正确地解析和运行 - 。也许可能性很低,但潜在的损害是世界末日。也许你不同意,这是一个自由的国家。
不管怎样,您想要YAML步长函数吗?您可以使用serverless.com或SAM(查看此处和此处)来实现这一点。
控制流·GCP和AWS都将工作流建模为一系列步骤;AWS将其称为“状态”。它们都允许任何步骤说明下一步要执行哪一步,并且都有类似切换的条件来根据工作流状态选择下一步。
但这是有很大区别的。在GCP中,如果某个步骤没有显式说明下一步的位置,则执行将移动到YAML中下一行上的任何步骤。我想这是一种习惯用法,基于编程语言所做的事情。在AWS中,如果您没有说明下一步是什么,那么您必须处于终端成功/失败状态;这与语法联系在一起。在GCP中,不能有名为“End”的步骤,因为Next:End表示工作流结束。有点语法味道吗?
我很难以这样或那样的方式形成对这件事的看法。GCP工作流可以更紧凑。AWS语法规则更简单、更一致。[这几乎就像是一位州语撰稿人真的对极简主义和句法完整性感到厌烦。]。我想这可能没什么不同吧?
GCP和AWS都有类似于子例程的语义的子工作流,但GCP是内部的,是工作流的一部分,而AWS是外部的,单独定义和管理的。这两种方法似乎都不疯狂。
工作流中的工作·工作流引擎实际上并不做任何工作,它们编排计算资源 - 函数和其他网络服务 - 来完成任务。在AWS中,Worker由名为Resource的字段标识,该字段在语法上是URI。目前用于标识工作者资源的所有URI都是Amazon风格的ARN。
目前,GCP主要假设是HTTP世界。您可以指定URL,您是否想要GET/POST/PATCH/DELETE(为什么没有PUT?),允许您填充头字段、将查询附加到URI、提供身份验证信息等。此外,您还可以给出存储结果的变量的名称。
我之所以说“大部分”,是因为在所有调用中:http.get示例中,我看到一个调用:nsys.sleep,所以架构允许其他类型的事情。
GCP有一个优势,那就是您可以调用任意HTTP端点。我真的很喜欢这一点:与,嗯,任何东西融合在一起。
在AWS架构中没有任何东西会妨碍我这样做,但是当我在那里的时候,这个特性从来没有被放在优先级列表的首位。
这是因为预先构建的集成似乎提供了更多的价值。有很多使用API的超级有用的服务,它们很难交谈。有些没有同步API,只是一劳永逸。或者有比HTTP更好的替代方案来解决这些问题。或者他们有众所周知的故障模式和解决方法来处理这些模式。因此,AWS附带了针对Lambda、AWS Batch、DynamoDB、ECS/Fargate、SNS、SQS、Glue、SageMaker、EMR、CodeBuild和STEP函数本身的预煮集成。这些服务中的每一个都采用了一种服务,这些服务可能比较复杂或难以交谈,并且在工作流步骤中很容易使用。
它的工作方式是“Resource”值类似于ARN:AWS:STATES:SQS:sendMessage,这意味着工作流应该发送SQS消息。
AWS的袖子里还有几个其他的集成技巧。一种是“回调任务”,服务启动一个任务,向它传递一个回调令牌,然后暂停工作流,直到有东西回调令牌,让步骤函数知道任务已经完成。如果您想要运行一项涉及到与人交互的任务,这一点尤其方便。
最后,AWS有“活动”。这些是轮询步骤函数以说“有工作给我吗?”的工作者任务。还有“这是你告诉我的工作成果”和“我要说我还在这里,真让人心跳”。事实证明,这些东西有很多用处。一种情况是,如果您希望转移固定数量的主机来执行工作流任务,例如,为了避免关系数据库超载。
因此,目前,AWS提供了更多的内置集成,并定期发布新的集成。话虽如此,我在GCP的体系结构中看不到任何阻止它最终走上类似道路的东西。
在AWS中,用于指定要做什么的工具稍微精简了一些:“这里有一个URI,它说明应该由谁来做这项工作,这里有一个JSON的BLOB作为初始输入。请弄清楚如何启动Worker并将数据发送给它。“。[这几乎就像是美国语言的贡献者是Web体系结构的铁杆粉丝,并将URI视为标识信息或服务单元的一个非常不透明的间接层。]
可靠性·这是工作流程带来的重要内容之一。在云中,任务有时会失败;这是生活中的现实。您希望您的工作流能够适当地重试,在必要时捕获异常,并在发生错误时重新路由工作流。换句话说,你想拿起每一件小事,然后用相当于尝试/抓住/最后的东西来包围它。
GCP和AWS都使用类似的机制来实现这一点:通过控制重试的次数和时间来捕获异常,并最终将其分派到工作流中的其他位置。GCP允许您命名重试策略并重用它,这很酷。但是它的语法很古怪。
AWS不遗余力地确保工作流程步骤不会因服务中的故障而丢失或中断。(更快、更便宜的Express工作流变体提供的保证仍然很好,但力度较小。)。我希望看到GCP关于服务预期可靠性的声明。
并行性:通常情况下,您希望工作流并行地编排它的一系列任务。AWS提供了两种方法来实现这一点:您可以获取一个数据项并将其并行提供给一系列不同的任务,或者您可以获取数组并将其元素提供给同一任务。在后一种情况下,您可以限制最大并发性,甚至可以强制一次处理一个。
GCP都是单线程的。我想没有什么建筑上的原因会让它在未来保持原样。
GCP中的工作流状态·现在有了真正的不同,这是一个很大的不同。当您启动工作流时,您向其提供数据,当它工作时,它会建立状态,然后使用该状态生成输出并做出工作流路由选择。
在GCP中,这都是通过工作流变量完成的。您可以将步骤的输出放入变量中。或者,您可以对它们赋值并对其进行算术运算,就像在编程语言中一样。因此,您可以构建如下循环结构:
-定义:分配:-array:[";foo";,";ba";,";r";]-result:";";-i:0-check_Condition:开关:-Condition:${len(Array)>;I}Next:Iterate Next:Exit_Loop-Iterate:Assign:-Result:${result+array[i]}-i:${i+1}Next:Check_Condition-Exit_Loop:Return:Concat_Result:${result}
变量是无类型的;可以是数字、字符串、对象、鱼或自行车。假设一个步骤的调出返回JSON。然后,GCP会将其解析成一个多级对象,其中顶层是一个对象,其中包含名为Header(对于HTTP Header)和Body的成员,然后Body具有解析后的JSON,然后您可以在末尾添加函数,这样您就可以编写如下咒语:
(DoubleValue是一个函数,而不是数据字段。那么,如果我的数据中有一个名为doubleValue的字段,该怎么办呢?(Ewwww.)。
同样,如果步骤调用返回PDF,您也可以将其放入变量中。如果对此调用doubleValue,我猜这是个例外?
变量名对于工作流是全局的,看起来有些变量名是保留的,例如http和sys。
…。而在AWS·,情况就大不相同了。到目前为止,AWS不使用变量。当工作流执行时,工作流状态作为JSON从一个步骤传递到下一个步骤。有一些运算符(InputPath、ResultPath、OutputPath、Parameters)用于拉出片段并将它们缝合在一起。
就像在GCP中一样,JSONPath语法用于挑选零碎的状态,但是第一步只是$,而不是变量的名称。
没有算术,但是您不需要像上例那样处理数组索引,因为并行性是内置的。
如果您想要进行奇特的操作来准备调用的输入或拆分某个人的输出,AWS会使用内置的PASS功能为您提供相当大的帮助;但是如果您想要奇特的操作并运行真正的过程代码,您可能需要一个Lambda来实现这一点。我们认为这是可以的;在保持优雅的同时,尽可能地声明地走得更远,因为当它发生故障时,这就是云,而现在云是有功能的。
虽然我还没有和GCP一起去做真正的工作,但目前我认为AWS方法是这里的赢家。首先,我讨厌全局变量 - ,因为在大多数阅读这篇文章的人出生之前,我就有充分的理由讨厌 - 。其次,YAML是一种用来做算术等工作的糟糕的编程语言。
第三,也是最重要的,当您想要进行严重的并发处理时会发生什么,我认为这是一个非常常见的工作流场景?GCP还没有真正内置并行性,但我打赌如果该产品获得任何吸引力,这种情况就会改变。将无类型、无作用域的全局变量与并行处理相结合是通向并发地狱的快车道。
AWS应用程序状态始终本地化到执行工作流中的某个位置,并且可以在您执行过程中记录和检查,因此可以直接用作调试资源。
[这几乎就像是State语言的贡献者精通函数编程,并且认为不变的消息对于跟踪可伸缩分布式系统中的状态是有意义的。]。
GCP变量具有熟悉的优点,与处理工作流状态的AWS“路径”原语相比,它的学习曲线可能更短。但是我真的不想拥有一个围绕对非类型化全局变量的并发访问而构建的大型任务关键型工作流。
定价·GCP比AWS便宜,但不比2019年末推出的Express工作流便宜。
呼叫任意HTTP端点的成本要高得多,这很有趣,但完全不令人惊讶。任何建立了通用呼叫到任何基础设施的人都知道这是一个很大的痛苦,因为这些呼叫可能会失败,而且这不是客户的问题,而是你的问题。
AUTH·这是一个我不会深入的领域,因为我对Google Cloud AUTH语义和最佳实践的理解很明显,因为它不存在。很高兴看到GCP的秘密管理器集成,特别是在HTTP调用方面。对于auth类型,您可以指定OIDC和OAuth2中的一个或两个;显然还需要进行更多的调查,这让我有点不知所措。
UX·我说的是控制台中的图形内容。根据Knapik的YouTube,GCP控制台看起来干净而有用。再一次,AWS的风格已经有了更多年的发展,只是包含了更多的东西。可能最大的不同之处在于,AWS绘制了工作流的小椭圆形和箭头图形格式,在工作流执行时为椭圆形着色,并允许您单击它们来检查任何工作流执行的输入和输出。这不仅仅是让人赏心悦目的,它是超级有帮助的。
您应该使用哪种工作流服务?·这非常简单。您应该使用声明指定的、完全托管的云本地服务,该服务可以调用各种工作进程,并结合重试和异常处理来实现高可靠性。而且,您应该使用您所在的任何公共云的本地云!就像我说的,很简单。
当STEP函数问世时,我关注的第一件事是如何管理更改,如蓝绿色部署和版本控制。有一件BurningMonk的作品展示了笨重但实用的答案……。GCP是如何做到这一点的?(我同意你关于全球化的邪恶…!)。
这真的给我留下了深刻的印象,它应该是一个具有多个云绑定的单一开源项目,而不是专有的东西。但是嘿..。