使用Lambda或Functions实现Express.js应用程序无服务器化——这是一个好主意吗?

17
免责声明: 我承认这更像是一个广泛的最佳实践问题,而不是一个具体的编程问题,但我相信 SO 社区是最好的受众对象。我知道有类似的问题 (在无服务器应用中是否应该使用 Express.js?),但是答案似乎不能回答我的问题。
我想将 Express.js 从 AWS Lightsail/EC2 迁移到无服务器应用程序中,因为这是典型的做法,Lambda 是我的首选。然而,一个整个框架和其上面的应用程序可能会有点笨重,不能被认为是一个函数,因此可能不适合在 AWS Lambda、Google 或 Azure Functions 上运行。虽然我相信它是可行的,但这是一个好主意吗?这种设置会破坏效率并复杂化处理会话状态等事情,最终会使无服务器函数失去意义吗?
3个回答

24

回答您的问题取决于您当前和未来的需求。我认为您应该始终提前规划,并确保您将要实现的当前基础设施可以升级以满足未来的需求。

您应该问自己以下这些问题:

  • 在未来,我是否需要一些websocket连接?
  • 我的请求路由中是否需要任何代理?
  • 随着时间的推移,我的应用程序会变得多么大?
  • 我期望在未来使用哪些AWS服务?

可伸缩性

出于许多原因,在lambda中使用Express.js并不是一个好主意:

  1. 您将为Lambda的执行支付更多费用,因为它将花费更长的时间运行,可能还需要更多内存。
  2. 延迟更高。
  3. 进行小的修改意味着重新部署所有应用程序代码到1个lambda上,因此只有1个故障点。
  4. 通常随着您添加更多功能,您的应用程序代码库将随着时间而增长。那个单片机存储库的维护将很痛苦,您可能会因遇到的错误而部署得比您想要的少。

成本效益

在Lambda上使用Express.js更加昂贵,因为您需要将任何方法代理到您的Lambda中,并使用API Gateway REST API而不是使用API Gateway HTTP API

HTTP APIs与REST APIs相比,更便宜高达71%

延迟

Lambda并不能像他们所宣传的那样,在没有服务器的情况下神奇地执行您的代码。当事件发生时,AWS将启动一个docker容器,等待其完全加载所有依赖项,然后运行处理程序。

对于在AWS EC2或AWS ECS上的普通Node.js服务器,这是一次性成本,因为您的服务器始终在运行,并且已经加载了所有依赖项,但不适用于lambda。

正如AWS所说:

这种方法[Express.js并代理所有请求到您的lambda]通常是不必要的,通常最好利用API Gateway中可用的本机路由功能。在许多情况下,Lambda函数中不需要Web框架,这会增加部署包的大小。 API Gateway还能够验证参数,减少了使用自定义代码检查参数的需要。它还可以提供对未经授权访问的保护以及一系列其他更适合在服务级别处理的功能。

组织大型无服务器应用程序的最佳实践

如何将Express框架转换为普通Lambda

为了简化您的生活,我建议您使用SAM CLI。使用它非常简单。

安装SAM CLI

如果您遵循Express应用程序的MVC模式,则只需要获取包含核心逻辑的服务文件

──src-ts
    ├───handlers
    │       getEvent.ts
    │
    ├───tests
    │   │   getEvent.tests.ts
    │   │
    │   └───utils
    │           utils.ts
    │
    └───utils
            utils.ts
            validation.ts

你的处理程序返回三个东西很重要:

  1. 头信息(JSON)
  2. 状态码(数字)
  3. 正文(字符串化)

你还需要一个 template.yml 文件来描述你的 Lambda 需要的基础设施。

AWSTemplateFormatVersion: 2010-09-09
Description: Describe the lambda goal

Transform:
    - AWS::Serverless-2016-10-31


Resources:
    # API Gateway
    LambdaAPI:
        Type: AWS::Serverless::Api
        Properties:
            StageName: StageName
            Cors:
                AllowMethods: "'POST, GET, OPTIONS'"
                AllowHeaders: "'*'"
                AllowOrigin: "'*'"


    # IAM Role
    LambdaRole:
        Type: AWS::IAM::Role
        Properties:
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    - Action:
                          - 'sts:AssumeRole'
                      Effect: Allow
                      Principal:
                          Service:
                              - lambda.amazonaws.com
            ManagedPolicyArns:
                - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
                - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
                - arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess

    GetEvent:
        Type: AWS::Serverless::Function
        Properties:
            Runtime: nodejs12.x
            Timeout: 180
            FunctionName: youLambdaName
            Handler: src/handlers/getEvent.handler
            Role: !GetAtt LambdaRole.Arn
            Events:
                Get:
                    Type: Api
                    Properties:
                        RestApiId: !Ref LambdaAPI
                        Path: /events/{eventid}
                        Method: GET

注意:我使用 TypeScript,但编译后会创建一个 src 文件夹。

以下是一些有助于更深入了解的资源:

总结

使用不含 Express 的 Lambda 优点:

  • 更好的可扩展性
  • 成本优化
  • 更低的延迟
  • 更高的可用性,因为你有多个 Lambda,每个业务逻辑都有一个,而不是只有一个 Lambda 运行所有业务逻辑

使用不含 Express 的 Lambda 缺点:

  • 需要修改现有代码
  • Lambda 初始化时间需考虑在开发逻辑时
  • 如果想要添加更多功能到 API 基础结构中,需要学习 SAM yaml 模板并阅读 AWS 文档。

充分利用 AWS 基础设施,不要试图反其道而行。AWS 服务之间以无缝和低延迟的方式协同工作。如果您想要实现“无服务器”,则应从基础架构中删除 Express。


3
如果您的应用程序需要很多资源才能正常运行,您可以考虑创建一个Docker镜像,并使用Fargate ECS来运行它,这被认为是一种无服务器选项。

1
将服务器分成小的微服务,托管在lambda脚本上,这将有助于您大有作为。
我已将我的服务器分解成几个微服务,以构建可扩展的系统。以下是您可以创建的典型lambda函数,以使其具备成本效益和可扩展性:
1. 用户数据管理 2. 认证 3. 面向特定用户的Web界面/API 4. 核心逻辑 5. 第三方集成
等等...
可扩展性:您无法自动获得可扩展性,除非手动配置或使用任何第三方软件来调整EC2或任何其他服务器上的可扩展性。
成本效益:由于lambda函数具有高可用性和每个API调用的计费方式,因此您实际上可以从预算中获得更多收益。
安全性:将每个Web应用程序分解为不同的lambda函数将为您提供更大的灵活性,以便为不同类型的用户提供访问权限,同时为每个单独的Web应用程序和负载均衡器配置API网关将成为一个重要的安全层,除了认证系统。
无论你是从头开始创建应用程序还是不是,服务器中包含的所有功能都将被分成小代码块,并且有很大的灵活性来测试和逐个构建每个应用程序。
使用Express,我没有看到这种灵活性和快速开发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接