首页 > 解决方案 > Express.js 应用程序无服务器,使用 Lambda 或函数 - 好主意吗?

问题描述

免责声明:我承认这更像是一个广泛的最佳实践问题,而不是一个特定的编程问题,但是,我相信 SO 一群是它的最佳受众。我知道这个类似的问题(我应该在无服务器应用程序中使用 Express.js 吗?),但答案似乎没有回答我的问题。

出于典型原因,我想将 Express.js 从 AWS Lightsail/EC2 迁移到无服务器,而 Lambda 是我的首选武器。然而,一个完整的框架连同其上的一个应用程序可能仍然被认为是一个函数,因此可能不适合在 AWS Lambda 或 Google/Azure Functions 上运行。虽然我确信这是可行的,但这是个好主意吗?这种设置不会降低效率并使处理诸如会话状态之类的事情复杂化,最终破坏无服务器功能的目的吗?

标签: expressaws-lambdaazure-functionsserverlessaws-serverless

解决方案


您的问题的答案取决于您当前和未来的需求。我认为您应该始终提前计划并确保您将实施的当前基础架构可以升级以满足未来的需求。

你应该问自己这些问题:

  • 将来我想要一些 websocket 连接吗?
  • 我的请求路由中是否需要任何代理?
  • 随着时间的推移,我的应用程序将有多大?
  • 我希望将来使用哪种 AWS 服务

可扩展性

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

  1. 您将为执行 Lambda 支付更多费用,因为它需要更多时间来运行,并且可能需要更多内存
  2. 延迟更高
  3. 做一个小的修改意味着在 1 个 lambda 上重新部署所有应用程序代码,因此只有 1 个故障点。
  4. 通常,随着您添加更多功能,您的应用程序的代码库会增加。维护那个单一的 repo 将是一件痛苦的事情,由于您可能遇到的错误,您将部署比您想要的更少。

成本效益

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

HTTP API 比 REST API 便宜 71%

潜伏

Lambda 不会在没有服务器的情况下神奇地执行您的代码,即使他们按原样推销它。当事件发生时,AWS 将启动一个 docker 容器,等待它完全加载您的所有依赖项,然后运行您的处理程序。

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

正如 AWS 所说:

这种方法 [Express.js and proxy all requests to your lambda] 通常是不必要的,通常最好利用 API Gateway 中可用的本机路由功能。在很多情况下,Lambda 函数中不需要 Web 框架,这增加了部署包的大小。API Gateway 还能够验证参数,减少使用自定义代码检查参数的需要。它还可以防止未经授权的访问,以及更适合在服务级别处理的一系列其他功能。

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

如何将 Express 框架转换为计划 Lambda

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

安装 SAM CLI

如果您正在为您的 Express 应用程序遵循 MVC 模式。您只需要将服务文件放在核心逻辑所在的位置。

我喜欢用于 lambda 的文件夹结构如下

假设它是一个小型日历应用程序

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

您的处理程序返回 3 件事很重要

  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

注意 我使用了打字稿,但是在编译时它正在创建一个src文件夹

一些资源可以更深入地帮助您:

总结

在没有 Express 的情况下使用 lambdas 的好处是:

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

在没有 Express 的情况下使用 lambdas 的缺点是:

  • 您需要修改现有代码
  • 在开发逻辑时,您的 lambda 的初始时间需要成为您思考的一部分
  • 当您想向 API 基础设施添加更多功能时,您需要学习 SAM yaml 模板并阅读 AWS 文档。

利用 AWS 基础设施,不要试图违背它。所有 AWS 服务都以无缝且低延迟的方式协同工作。如果你想去“无服务器”,你应该从你的基础设施中删除 Express。


推荐阅读