首先要说的是,“serverless”技术必须涉及到服务器。我只是用这个术语来描述这种将任务处理和调度从服务器管理中抽象出来的方法和技术。在2012年一篇关于ReadWrite软件和应用程序未来的文章中,我对“无服务器”的描述如下。“无服务器”一词并不意味着不再涉及服务器。这只是意味着开发人员不必再对它们给予太多关注。计算资源用作服务,无需管理物理容量或限制。服务提供商越来越多地承担管理服务器、数据存储和其他基础设施资源的责任……无服务器架构允许开发人员将他们的注意力从服务器级别转移到任务级别。无服务器解决方案通过消除后端基础设施的复杂性,使开发人员能够专注于他们的应用程序或系统需要做什么。在那篇文章发表的时候,“无服务器”这个词并没有被广泛接受,从当时HackerNews上的评论中可以看出。但随着一些Serverless平台的诞生,以及微服务和事件驱动架构的重要性越来越高,幸运的是这些疑虑逐渐平息了。ServerlessArchitectureUsageScenarioExample为了更好地理解这项技术,***基于一个真实使用场景的例子来讨论它,所以假设我们想使用一个Serverless管道来处理电子邮件和检测垃圾邮件。它是事件驱动的,因为当收到一封电子邮件时,它会产生一系列专门针对该电子邮件执行的作业或功能。在此管道中,您的任务可能是解析电子邮件中的文本、图像、链接、邮件属性和其他项目或嵌入对象。每个项目或元素可能有不同的处理要求,这又需要一个或多个单独的任务,甚至需要自己的处理管道或顺序。例如,可以跨多个不同的处理向量分析图像链接以确定图像的内容和真实性。根据消息分数和结果(垃圾邮件与否),将采取各种行动,这可能反过来涉及其他无服务器功能。无服务器架构分析无服务器环境中的基本单元是一个任务或作业,它围绕特定工作负载的处理被实例化和执行。任务处理从编程开始就存在,所以它也不是全新的东西。但鉴于处理这些工作负载的高度分布式特性和抽象方式,有必要对具体的实现级别有广泛的了解。同步与异步虽然处理任务的性质(无论是同步还是异步)通常是一个平台问题,但它也是在任务级别需要考虑的一个重要因素。传统的工作和作业处理系统在很大程度上是异步的,这意味着调用进程不会保持与执行任务处理组件的持久连接。作业将排队,因此它们可能不会立即运行。调用函数和处理器之间的唯一特定连接将任务排队以运行。(请注意,某些平台可能允许获取任务状态,但通过API调用而不是直接/持久连接)。许多新的无服务器平台允许同步处理,从而保持连接并在处理功能时客户端等待。同步处理的好处是可以直接从处理平台获取结果,而异步处理,获取结果必须单独调用。我将在平台部分详细介绍,尽管一般规则是同步处理适用于轻量级功能(类似于获取天气信息的API调用),而异步处理更多是关于处理作业(音频转录或作为作业的一组事件的小批量处理),并且启动处理的应用程序/组件/功能不是处理结果的应用程序/组件/功能。无状态无论采用何种方法,开发微服务和/或无服务器功能的核心原则之一是每个服务或方法都应被视为无状态的。(小编:在高可用架构组的讨论分享中也多次提到Stateless)。无状态意味着每个任务都是一个单独且不同的处理请求,其中包含足够的信息来满足该请求。服务和方法不应存储任何独特的软件配置或状态。任何配置数据都应来自方法外部,通常作为任务的一部分或通过平台内的配置服务。此方法应仅用于其计算资源,仅用于处理单个工作负载。此外,应该有一个不同的开始和结束状态,并且服务或方法应该以相同的方式处理每个任务。借用干净的代码、糟糕的代码和糟糕的微服务和无服务器功能[1]文章的原则,我们应该关注并使用单一责任原则(SRP)[2]。考虑无服务器函数的一个好方法是每个函数应该有一个且只有一个维度或变化向量。换句话说,如果有多种方法可以扩展一个函数(例如,将检查多个特征的图像分析),那么每个向量应该有两个或更多不同的函数。在我们使用的用例中,每封电子邮件都是一个单独的事件,因此每封电子邮件都有一个单独的任务序列。每个任务都将承载为相应任务或方法提供处理的数据。短暂的无服务器功能也是短暂的——这意味着它们只持续有限的时间。无服务器应用程序的基础是围绕事件处理和为这些事件提供服务时发生的任务处理。强大的容器技术的出现,使得任务可以在分布式环境中处理,并在运行时决定在何处运行。换句话说,任务处理基本上变成了容器处理,容器是在任务基础上创建和删除的。例如,电子邮件处理示例中的每个任务仅持续对特定电子邮件执行特定操作。完成后,任务和容器应终止。可能存在需要持久或长时间运行的进程的情况,例如实现应用程序服务器或API服务器,我们通常将其置于无服务器范例之外。在大多数情况下,当您有您认为可能需要的长时间运行的任务时,可能有一些方法可以避免这种开销。例如,无服务器平台、消息队列或其他组件可能能够满足任何路由需求。同样,计划任务可能能够提供定期状态检查或处理周期。这里的示例是集成和处理来自各种物联网设备的流数据。如果数据收集在一个或多个队列或数据库中,则计划作业可以定期(和频繁)运行,查看队列或数据库中的数据,并启动一个或多个子任务以在每个队列或数据库上执行以进行合并和加工切片。请注意,在实际处理场景中,容器可能不会在每个任务后终止,主要是出于性能原因。容器可以从一个任务持续到下一个任务,但它们的状态和存储将被擦除和重置,从而使每个任务或事件处理循环孤立且短暂。幂等性幂等性是微服务和serverless功能内置的一个关键属性(编者:在高可用架构组的讨论和分享中,这个词也被反复提及)。在基本层面上,能够运行重复的任务并获得相同的结果。也可以使多个重复请求与单个请求具有相同的效果。这是第二个定义,当任务以高度并发和异步的方式运行时,它对设计至关重要。在任何作业处理环境中,任务可能由于多种原因(服务器崩溃、资源限制、第三方服务超时、任务超时等)而无法完成。在其他情况下,任务可以完成,但可能已调用重复的处理请求。这方面的一个例子是为超时注册消息的队列,因为任务可能仍在处理请求(因此没有及时删除或取消保留消息)。结果,队列可能会触发对该消息的另一个处理请求。简单地继续处理这些任务——将它们放入队列或将它们写入数据库可能会产生不良影响,尤其是在事务情况下。例如,将生成两个重复的订单。这是最重要的事情,然后确保只有一个请求处理同一任务。正是出于这个原因,在无服务器平台(与大多数其他处理领域一样)中,开发人员需要在处理之前和/或写入或输出结果之前对重复性任务执行检查。另一种思考方式,用开发者朋友的话说就是“想象一下,如果在中途处理任务的时候服务器崩溃了,重试任务。或者,如果只是排队或者调度了两次,你怎么办?”需要做的,以确保您不会覆盖数据,添加重复事务,因为它可能会运行多次。”因此,在处理周期中,在适当的点进行检查和验证,以确保工作尚未执行。多语言编程(Polyglot)多语言指的是使用多种语言进行编程。在无服务器编程的上下文中,它指的是用多种语言编写和执行任务的能力。虽然每个功能可能只是一种语言,但正确的无服务器平台应该能够处理多种语言。这意味着它还应该提供显着级别的代码独立性,允许开发人员透明地工作,而无需担心操作系统和服务器级别的依赖性。多语言的优势在于能够使用正确的工具来完成不同的任务。或者,为合适的团队提供适合他们的工具。实践中经常发生的情况是,如果你有一把锤子,在你看来一切都像钉子。使用单一语言通常会限制解决问题的方法。开发人员可能难以适应该语言的代码包来完成他们的需求,而实际上其他语言的其他库可能会更好地达到目的。为了计算贝叶斯统计或进行机器学习,您可能希望使用用C、C++、Python或Java编写的包。同样,与您合作的开发团队可能精通特定的网络爬虫包,该包是为特定语言编写的(例如用Ruby编写的Nokogiri)。能够利用这些知识和经验可以消除开发周期并降低项目延迟或失败的风险。请注意,许多较新的无服务器平台目前仅支持少数几种语言,但我预计这种情况会在今年内迅速改变。(例如IronWorker,可以处理大多数通用语言和可执行代码。)兼容性serverless任务需要考虑两个兼容性顺序。第一个是任务之间,第二个是版本之间。分解任务时,组件之间需要强大的服务契约和规范。规范的API格式可以解决通用身份验证和传输协议的部分问题,但对于自定义功能和服务,开发人员仍然需要定义有意义且易于理解的输入和输出模式。除了干净的界面,开发人员还需要解决版本控制要求。例如,假设函数X在平台内运行,它调用函数Y,如果函数Y在没有让函数X知道并且设计得当的情况下被更新,它可能会在处理时失败或者它可能会产生不正确的结果(或者它会导致预期原始结果的任务中的下游失败)。与代码包一样,无服务器任务中的更改和更新可以通过应用程序发布。在代码包的情况下,这些冲突可能会被打包和编译工具提前捕获。但是,对于微服务和无服务器编程,可能只有在运行服务时才会发现问题(***在测试或模拟环境中)。这意味着,由于所有这些无状态以及任务和服务独立性,团队不仅需要注意设计良好构建的接口,还需要解决向后兼容性意识。一种帮助可能是使用语义版本控制[3]来描述/控制无服务器任务。它并不完美,但随着此版本控制约定的传播,它为可能正在使用您创建的任务的其他开发人员提供了一些基础。
