Express.js 无服务器应用程序,使用 Lambda 或 Functions - 好主意吗?
Express.js app serverless, using Lambda or Functions - a good idea?
免责声明:我承认这更像是一个广泛的最佳实践问题,而不是一个特定的编程问题,但是,我相信 SO 群是它的最佳听众。我知道这个类似的问题 (),但答案似乎没有回答我的问题。
出于典型原因,我想将 Express.js 从 AWS Lightsail/EC2 迁移到无服务器,而 Lambda 是我的首选武器。然而,整个框架连同其上的应用程序可能有点笨重,仍被视为 函数 ,因此可能不适合作为 AWS Lambda 上的 运行 , 或 Google/Azure 函数。虽然我确信 it is doable,但这是个好主意吗?这种设置不会降低效率并使处理诸如会话状态之类的事情复杂化,最终会破坏无服务器功能的目的吗?
如果像您所说的那样运行有点繁重,您可能会考虑为您的应用程序创建一个 docker 映像,然后 运行 使用被认为是无服务器选项的 Fargate ECS。
您问题的答案取决于您当前和未来的需求。我认为您应该始终提前计划并确保您将实施的当前基础设施可以升级以满足未来的需求。
你应该问自己这些问题:
- 将来我想要一些 websocket 连接吗?
- 我的请求路由中需要任何代理吗?
- 随着时间的推移,我的应用程序会变成多大?
- 我希望将来使用哪种 AWS 服务
可扩展性
在 lambda 中使用 Express.js 不是一个好主意,原因有很多:
- 您将为执行 Lambda 支付更多费用,因为它需要更多时间 运行 并且可能需要更多内存
- 延迟更高
- 做一个小修改意味着在 1 个 lambda 上重新部署所有应用程序代码,因此只有 1 个故障点。
- 通常情况下,您的应用程序的代码库会随着您添加更多功能而增长。维护那个单一的 repo 将是一件很痛苦的事情,而且由于您可能遇到的错误,您将部署得比您想要的少。
性价比
Express.js 在 Lambda 上更昂贵,因为您需要使用 API 网关 REST API 将任何方法代理到您的 lambda 中,而不是使用 API 网关 HTTP API
HTTP APIs are up to 71% cheaper compared to REST APIs
延迟
Lambda 不会在没有服务器的情况下神奇地执行您的代码,即使他们按原样销售它。当事件发生时,AWS 将启动一个 docker 容器,等待它完全加载您的所有依赖项,然后 运行 您的处理程序。
对于 AWS EC2 或 AWS ECS 上的普通 Node.js 服务器,这是一次性成本,因为您的服务器总是 运行ning 并且您的所有依赖项都已加载但不在您的 lambda 上。
正如 AWS 所说:
This approach [Express.js and proxy all requests to your lambda] is generally unnecessary, and it’s often better to take advantage of the native routing functionality available in API Gateway. In many cases, there is no need for the web framework in the Lambda function, which increases the size of the deployment package. API Gateway is also capable of validating parameters, reducing the need for checking parameters with custom code. It can also provide protection against unauthorized access, and a range of other features more suited to be handled at the service level.
Best practices for organizing larger serverless applications
如何将Express框架转换成Lambda计划
为了简化您的生活,我建议您使用 SAM CLI。上手非常简单
如果您的 Express 应用遵循 MVC 模式。您只需要将服务文件放在核心逻辑所在的位置。
我喜欢用于 lambda 的文件夹结构如下
假设它是一个小日历应用程序
──src-ts
├───handlers
│ getEvent.ts
│
├───tests
│ │ getEvent.tests.ts
│ │
│ └───utils
│ utils.ts
│
└───utils
utils.ts
validation.ts
重要的是你的处理程序 returns 3 件事
- Headers (JSON)
- statusCode(数字)
- Body(字符串化)
您还需要一个 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
文件夹
一些资源可以更深入地帮助您:
- https://aws.amazon.com/blogs/compute/going-serverless-migrating-an-express-application-to-amazon-api-gateway-and-aws-lambda/
- https://dev.to/brightdevs/how-to-convert-an-express-app-to-aws-lambda--44gc
- https://medium.com/hackernoon/how-to-deploy-a-node-js-application-to-aws-lambda-using-serverless-ae7e7ebe0996
- https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html
总结
在没有 Express 的情况下使用 lambda 的好处是:
- 更好的可扩展性
- 成本优化
- 更低的延迟
- 更高的可用性,因为每个业务逻辑都有多个 lambda,而不是 运行 全部
在没有 Express 的情况下使用 lambda 的缺点是:
- 您需要修改现有代码
- 在开发逻辑时,lambda 的初始时间需要成为您思考的一部分
- 如果您想向 API 基础架构添加更多功能,则需要学习 SAM yaml 模板并阅读 AWS 文档。
利用 AWS 基础设施,不要试图违背它。所有 AWS 服务都以无缝和低延迟的方式协同工作。如果你想“无服务器”,你应该从你的基础设施中删除 Express。
将您的服务器划分为托管在 lambda 脚本上的小型微服务将大有帮助。
我已经将我的服务器分解成几个微服务来构建一个可扩展的系统。以下是您通常可以创建的上述 lambda 函数,以使其具有成本效益和可扩展性
- 用户数据管理
- 身份验证
- 用户特定网站interfaces/APIs
- 核心逻辑
- 第三方集成
等...
可扩展性:如果不手动配置或不使用任何可以在 EC2 或任何其他服务器上调整可扩展性的第三方软件,您将无法获得自动可扩展性
成本效益:由于 lambda 函数具有高可用性和按 API 调用计费,您实际上可以从预算中获得更多收益。
安全性:在不同的 lambda 函数中分解每个 Web 应用程序将使您更灵活地为不同类型的用户提供访问权限以及 API 每个单独的 Web 应用程序的网关配置和除了身份验证系统之外,负载平衡器将是一个很好的安全层。
您是否从头开始创建应用并不重要。服务器中包含的所有功能都将被分成小块代码,并且有很大的灵活性来测试 运行 每个应用程序在您构建它们时一个一个地进行。
使用 Express,我还没有见过这种灵活性和快速开发。
免责声明:我承认这更像是一个广泛的最佳实践问题,而不是一个特定的编程问题,但是,我相信 SO 群是它的最佳听众。我知道这个类似的问题 (
出于典型原因,我想将 Express.js 从 AWS Lightsail/EC2 迁移到无服务器,而 Lambda 是我的首选武器。然而,整个框架连同其上的应用程序可能有点笨重,仍被视为 函数 ,因此可能不适合作为 AWS Lambda 上的 运行 , 或 Google/Azure 函数。虽然我确信 it is doable,但这是个好主意吗?这种设置不会降低效率并使处理诸如会话状态之类的事情复杂化,最终会破坏无服务器功能的目的吗?
如果像您所说的那样运行有点繁重,您可能会考虑为您的应用程序创建一个 docker 映像,然后 运行 使用被认为是无服务器选项的 Fargate ECS。
您问题的答案取决于您当前和未来的需求。我认为您应该始终提前计划并确保您将实施的当前基础设施可以升级以满足未来的需求。
你应该问自己这些问题:
- 将来我想要一些 websocket 连接吗?
- 我的请求路由中需要任何代理吗?
- 随着时间的推移,我的应用程序会变成多大?
- 我希望将来使用哪种 AWS 服务
可扩展性
在 lambda 中使用 Express.js 不是一个好主意,原因有很多:
- 您将为执行 Lambda 支付更多费用,因为它需要更多时间 运行 并且可能需要更多内存
- 延迟更高
- 做一个小修改意味着在 1 个 lambda 上重新部署所有应用程序代码,因此只有 1 个故障点。
- 通常情况下,您的应用程序的代码库会随着您添加更多功能而增长。维护那个单一的 repo 将是一件很痛苦的事情,而且由于您可能遇到的错误,您将部署得比您想要的少。
性价比
Express.js 在 Lambda 上更昂贵,因为您需要使用 API 网关 REST API 将任何方法代理到您的 lambda 中,而不是使用 API 网关 HTTP API
HTTP APIs are up to 71% cheaper compared to REST APIs
延迟
Lambda 不会在没有服务器的情况下神奇地执行您的代码,即使他们按原样销售它。当事件发生时,AWS 将启动一个 docker 容器,等待它完全加载您的所有依赖项,然后 运行 您的处理程序。
对于 AWS EC2 或 AWS ECS 上的普通 Node.js 服务器,这是一次性成本,因为您的服务器总是 运行ning 并且您的所有依赖项都已加载但不在您的 lambda 上。
正如 AWS 所说:
This approach [Express.js and proxy all requests to your lambda] is generally unnecessary, and it’s often better to take advantage of the native routing functionality available in API Gateway. In many cases, there is no need for the web framework in the Lambda function, which increases the size of the deployment package. API Gateway is also capable of validating parameters, reducing the need for checking parameters with custom code. It can also provide protection against unauthorized access, and a range of other features more suited to be handled at the service level.
Best practices for organizing larger serverless applications
如何将Express框架转换成Lambda计划
为了简化您的生活,我建议您使用 SAM CLI。上手非常简单
如果您的 Express 应用遵循 MVC 模式。您只需要将服务文件放在核心逻辑所在的位置。
我喜欢用于 lambda 的文件夹结构如下
假设它是一个小日历应用程序
──src-ts
├───handlers
│ getEvent.ts
│
├───tests
│ │ getEvent.tests.ts
│ │
│ └───utils
│ utils.ts
│
└───utils
utils.ts
validation.ts
重要的是你的处理程序 returns 3 件事
- Headers (JSON)
- statusCode(数字)
- Body(字符串化)
您还需要一个 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
文件夹
一些资源可以更深入地帮助您:
- https://aws.amazon.com/blogs/compute/going-serverless-migrating-an-express-application-to-amazon-api-gateway-and-aws-lambda/
- https://dev.to/brightdevs/how-to-convert-an-express-app-to-aws-lambda--44gc
- https://medium.com/hackernoon/how-to-deploy-a-node-js-application-to-aws-lambda-using-serverless-ae7e7ebe0996
- https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html
总结
在没有 Express 的情况下使用 lambda 的好处是:
- 更好的可扩展性
- 成本优化
- 更低的延迟
- 更高的可用性,因为每个业务逻辑都有多个 lambda,而不是 运行 全部
在没有 Express 的情况下使用 lambda 的缺点是:
- 您需要修改现有代码
- 在开发逻辑时,lambda 的初始时间需要成为您思考的一部分
- 如果您想向 API 基础架构添加更多功能,则需要学习 SAM yaml 模板并阅读 AWS 文档。
利用 AWS 基础设施,不要试图违背它。所有 AWS 服务都以无缝和低延迟的方式协同工作。如果你想“无服务器”,你应该从你的基础设施中删除 Express。
将您的服务器划分为托管在 lambda 脚本上的小型微服务将大有帮助。
我已经将我的服务器分解成几个微服务来构建一个可扩展的系统。以下是您通常可以创建的上述 lambda 函数,以使其具有成本效益和可扩展性
- 用户数据管理
- 身份验证
- 用户特定网站interfaces/APIs
- 核心逻辑
- 第三方集成
等...
可扩展性:如果不手动配置或不使用任何可以在 EC2 或任何其他服务器上调整可扩展性的第三方软件,您将无法获得自动可扩展性
成本效益:由于 lambda 函数具有高可用性和按 API 调用计费,您实际上可以从预算中获得更多收益。
安全性:在不同的 lambda 函数中分解每个 Web 应用程序将使您更灵活地为不同类型的用户提供访问权限以及 API 每个单独的 Web 应用程序的网关配置和除了身份验证系统之外,负载平衡器将是一个很好的安全层。
您是否从头开始创建应用并不重要。服务器中包含的所有功能都将被分成小块代码,并且有很大的灵活性来测试 运行 每个应用程序在您构建它们时一个一个地进行。
使用 Express,我还没有见过这种灵活性和快速开发。