原文:Fast growing architectures with serverless and .NET Core

作者:Samuele Resca

Serverless 技术为开发人员提供了一种快速而独立的方式将实现投入生产。这种技术在企业的技术栈中日益流行,自 2017 年以来,它一直是 ThoughtWorks 技术雷达的实验级别的技术[译注:技术雷达是 ThoughtWorks 每半年发布的前沿技术解析]。

本篇文章的第一部分介绍了有关 Serverless 计算的基本概念。第二部分展示了如何构建 .NET Core 的 Lambda 函数,其中使用了 AWS 的 Serverless 框架。

Serverless 计算的好处

Serverless 技术是 FaaS(功能即服务)技术体系的一部分。随着云计算的采用,这些技术变得越来越受欢迎。如今,serverless 实现被提升为云计算提供商的首选技术,无论是私有云还是公有云。

此外,典型的软件服务和系统会通过在内存中保留大量数据并在复杂数据源中写入成批数据来完成操作。
然而一般而言,像 Serverless 一样的 FaaS 技术旨在通过尽可能快地处理许多小请求和事件,来使我们的系统保持快速响应。Serverless 组件通常与运行它们的云服务商所提供的事件紧密耦合:一个通知、一个队列调度的事件或者一个来自 API 网关的请求,都被视为此组件中包含的一小部分计算的触发器。这也就是云服务商的定价系统基于请求数而不是基于计算时间的主要原因。

再者,serverless 组件通常在执行时间上有一些限制。与每种技术一样,serverless 并不适合每一个解决方案和系统。但是事实上,它确实简化了软件工程师的一些工作,lambda 部署周期通常很快,开发人员只需要做少量工作就可以快速将新功能投入生产。此外,使用 serverless 技术构建组件意味着开发人员无需担心扩展问题或故障,让云提供商去关心这些问题吧。

最后,我们还应该知道 serverless 函数是无状态的。因此,基于此技术构建的每个系统都更加模块化和松耦合。

Serverless 的痛点

但是这种能力和敏捷性却不是没有代价的。首先,serverless 函数是在云上执行的,它们通常由与云提供商紧密耦合的事件触发,因此调试它们并不容易。这就是为什么要使它的作用域保持尽可能小,并且始终将函数的核心逻辑与外部组件和事件分隔开的原因。此外,用单元测试和集成测试覆盖 serverless 代码非常重要。

其次,就像微服务架构一样,它具有大量的服务,但是关注的范围很小,因此很难对 serverless 的组件进行监控,某些问题也很难检测。总之,很难对不同的 serverless 组件之间的体系结构和依赖性有一个全面的认识。因此,云提服务商和第三方公司都在提供监控和系统分析功能的一体式工具上投入了大量资金。

体验一下 serverless 计算

现如今,根据业务需求快速进化的架构以往任何时候都更为重要。数据驱动的体验是这个过程的一部分。此外,在发布新功能之前,我们应该实现MVP(译注:最小可行化产品)并在部分客户群上测试它。如果实验结果是肯定的,则值得在MVP上进行投资,以将其转化为我们产品的功能。

是的,serverless 计算提供了这样一种方法,可以在不考虑基础设施的情况下快速进化我们的架构。Serverless 轻量级开销提供了一种实现一次性 MVP 的方法,用于试验新功能和新特性。此外,它们还可以很容易地启动和关闭。

使用 .NET Core 来实现 AWS Lambda 函数

这一节将介绍使用 .NET Core 的一些 AWS Lambdas 的简单实现。该例子涉及三个关键技术:

  • AWS 是承载我们 serverless 功能的云服务商;
  • serverless 框架,它是将 Lambdas 放入 AWS 的非常有用的工具。作为一个通用的框架,它兼容所有主要的云服务商;
  • .NET Core 是微软提供的开源的、跨平台的框架;

我们将要讨论的示例也放在了 GitHub 上,URL 如下: serverless/examples/aws-dotnet-rest-api-with-dynamodb。该示例是 serverless 框架提供的一些模板项目的一部分。

AWS Lambda 项目遵循以下功能架构:

总结一下,该功能实现了对数据的一些读取/写入操作。客户端通过API网关发出HTTP请求,lambda 项目定义了三个函数:GetItem、InsertItem 和 UpdateItem。它们都对 DynamoDB 表进行操作。

项目结构

我们将要实现的解决方案具有以下项目结构:

  • src/DotNetServerless.Application 该项目包含了由 Serverless 执行的核心逻辑;
  • src/DotNetServerless.Lambda 该项目包含了 Serverless 函数的入口点以及所有与 AWS 紧密耦合的组件;
  • tests/DotNetServerless.Tests 该项目包含了 Serverless 功能的单元测试和集成测试;

领域项目

让我们从 application 层开始分析。项目的核心实体是 Item 类,它表示 DynamoDB(译注:AWS的一种数据库) 表中存储的实体:

using Amazon.DynamoDBv2.DataModel;  namespace DotNetServerless.Application.Entity {   public class Item   {     [DynamoDBHashKey]     public string Id { get; set; }     [DynamoDBRangeKey]     public string Code { get; set; }     [DynamoDBProperty]     public string Description { get; set; }     [DynamoDBProperty]     public bool IsChecked { get; set; }   } }

实体的字段使用了一些特性进行修饰,以便使用 DynamoDb 存储模型映射它们。Item 实体被 IItemsRepository 接口引用,该接口定义用于存储数据的操作:

using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; using Amazon.DynamoDBv2.DocumentModel; using DotNetServerless.Application.Entities; using DotNetServerless.Application.Infrastructure.Configs;  namespace