无服务器架构:技术要点与挑战应对
1. 服务级别协议(SLAs)与多区域部署
无服务器架构的一个显著优势在于其按使用量计费。除存储成本外,无服务器服务的多区域部署相比单区域部署,成本并不会大幅增加。多区域部署有助于提高SLA保障,为用户提供更可靠的服务。
2. 无状态微服务
传统应用中,会话可以跟踪用户的多个请求,并在应用的不同部分之间共享信息,这种方式被称为有状态。而无服务器微服务是临时的,不会保留过去请求的任何信息,每个请求都被视为全新的请求,这就是无状态。这要求开发者重新思考应用结构以及如何在不同请求之间传递信息,对于刚接触无服务器架构的开发者来说是一项挑战。
3. 延迟问题及解决策略
延迟是指发送请求后到收到响应的时间间隔。糟糕的延迟会导致应用响应缓慢,影响用户体验。解决延迟问题主要从代码效率入手:
-
优化代码
:选择适合微服务的编程语言,如NodeJS和Python。Python在处理加密、压缩和复杂文件处理等重型任务时比NodeJS更高效。
-
避免使用庞大的库和框架
:许多库和框架不适合事件驱动架构,可能会导致延迟等问题。例如,一些提供服务器体验的库会使Lambda在无实际执行任务时仍保持运行,直到超时。
-
使用AWS Graviton芯片组
:如果代码允许,可在Lambda中使用该芯片组,它是一种ARM处理器,能提供高达19%的性能提升,同时成本降低20%。
-
进行基准测试
:对不同语言和Lambda内存设置进行基准测试,找到微服务的最佳配置。但要注意,公开的基准测试可能不能准确反映实际微服务的性能,应使用实际微服务进行测试。
-
使用并行请求
:在可能的情况下,使用并行请求来减少延迟。以下是一个NodeJS中使用Promise的示例:
// 上传文件到S3
function uplToS3File(fileName) {
const file_path = `${__dirname}/${fileName}`;
const fileContent = fs.readFileSync(file_path);
let s3 = new AWS.S3();
const params = {
Bucket: 'likz-demo-bucket',
Key: fileName,
Body: fileContent
};
console.log("Uploading to S3");
return s3.upload(params).promise();
}
// 创建文件元数据
function createFileMeta(name) {
let docClient = new AWS.DynamoDB.DocumentClient();
let params = {
TableName: 'demo_ddb',
Item: {
name,
url: `s3://${BUCKET_NAME}/${name}`
}
};
console.log("Adding a new item...");
return docClient.put(params).promise();
}
let myPromises = [];
const file_name = 'demofile.txt';
myPromises.push(uplToS3File(file_name));
myPromises.push(createFileMeta(file_name));
Promise.all(myPromises).then(result => {
const s3_success = result[0];
const ddb_success = result[1];
if (s3_success && ddb_success)
console.log('all success');
else
console.log('error');
});
4. 完全托管的扩展
自动扩展是无服务器架构的优势之一,但如果在应用基础设施或代码中不设置限制,可能会导致预算超支。在API Gateway中,可以为每个用户创建唯一的API密钥,并将其分配给使用计划。使用计划可以对分配的API密钥应用限流限制,包括每秒最大请求数和特定时间段(如每月)的最大请求数。此外,无服务器架构可以相对容易地跟踪单个用户,从而实现对用户活动的监控,限制资源的过度使用,并根据实际使用情况进行用户或跨部门计费。
5. 技术成熟度
虽然可以使用多种编程语言创建微服务,但传统的成熟Web应用框架往往不支持无服务器架构,因为它们可能与事件驱动的性质不兼容。一些库和语言已经发展为更好地支持无服务器架构,建议选择采用模块化方法的库和语言,只包含所需的功能。例如,AWS JavaScript SDK版本3就采用了模块化方法。同时,要注意许多小众库可能尚未经过实际应用的极端测试,在将其集成到微服务中时,需要关注其最后更新时间和维护情况。
组织在使用无服务器等新兴技术时,应密切关注相关服务的更新日志和云提供商的最新功能更新。团队可以通过变通方法克服服务限制,随着客户需求的增加,AWS通常会提供新的功能来解决这些限制。组织还可以通过AWS Wishlist等渠道提出改进请求,通过AWS博客监控新功能和特性发布,并将RSS订阅源集成到Slack频道中方便获取信息。此外,参与云服务的预览版可以让组织提前体验新服务,评估其适用性。成为AWS大使可以获取服务路线图,但需遵守保密协议。
6. 服务限制
- 内存限制 :Lambda的内存可以在128 MB到10 GB之间配置,按GB - 毫秒计费。内存分配越多,每毫秒的费用越高,因此需要选择合适的内存大小,并监控内存使用情况进行调整。微服务分配的CPU核心数与内存量相关,可能需要在成本和执行速度之间进行权衡。如果微服务需要超过10 GB的内存或相关CPU,可考虑使用容器。
- 代码大小限制 :微服务代码压缩后最大为50 MB,解压缩后为250 MB,包括配置的Lambda层。一般来说,微服务应保持较小规模,以1 - 5个敏捷用户故事为指导。对于需要更多存储的用例,如机器学习模型或搜索索引,可以使用最大为10 GB的Lambda容器镜像。
-
执行时间限制
:Lambda的最大超时时间为15分钟。如果微服务代码提前完成,执行将停止并停止计费。为避免微服务过早结束,通常设置较高的超时时间,但要注意一些错误和不适合该环境的框架可能导致微服务在无实际操作时仍运行,产生不必要的费用。如果微服务运行时间超过15分钟,可以考虑以下解决方法:
- 使用Step Functions :将应用拆分为更小的步骤,使用Step Functions创建多步骤工作流,处理等待、重试和错误处理,等待过程不产生费用。
- 使用SQS或EventBridge :对于简单工作流,微服务启动长时间运行的过程后,将任务添加到SQS或EventBridge,然后终止。SQS可以配置可见性延迟,EventBridge可以安排未来的任务,延迟结束后触发后续的Lambda继续处理。
- 使用容器 :如果微服务需要超过15分钟的实际执行时间,容器是更好的选择,因为容器没有服务超时限制,并且可以始终运行。如果可以采用事件驱动方法,可以使用Lambda按需启动容器。
- 请求和响应大小限制 :请求和响应大小限制为6 MB,通常足以处理事件消息和JSON数据。但在处理媒体文件等大请求时,可采用以下方法:当客户端需要发送大文件时,通过API Gateway端点请求上传URL,关联的Lambda微服务创建并返回带有过期日期和可选文件大小范围的签名S3 POST URL,客户端通过该URL直接将文件上传到存储桶,最后客户端将文件元数据和用户输入提交给API,关联的Lambda微服务处理新文件。
- 存储限制 :2022年,Lambda临时存储增加到10 GB。如果需要更多或更持久的存储,可以使用S3或为Lambda附加EFS。EFS是一种NFS兼容的网络驱动器,可以挂载到Lambda微服务中,提供更大的存储容量。EFS支持多并发客户端和文件锁定,可扩展到PB级数据。内部缓存可以加快多个微服务实例对同一文件的重复读取。EFS的延迟低于S3,但高于本地临时存储,成本高于S3,且Lambda临时存储包含在执行成本中。此外,对于特定用例,可以通过Lambda流式传输数据,通常是从源S3存储桶流到目标S3存储桶,适用于支持此功能的文件格式,如CSV。
7. 学习曲线
应用团队在采用无服务器架构时,需要认识到它与传统云应用架构有很大不同。无服务器架构中,微服务在请求之间实际上并不存在,应用可以快速扩展,资源仅根据代码需求确定,不考虑潜在用户数量。在Lambda微服务中,需要避免以下常见的反模式:
-
微服务规模过大
:保持微服务的范围小,以1 - 5个敏捷用户故事为指导,使用事件风暴来拆分大型单体应用。
-
避免在Lambda层中使用共享代码
:Lambda层用于分离第三方代码和自定义代码,若要避免代码重复,应在部署前在本地处理,并使用版本控制管理共享代码的更改。
-
避免长时间等待
:在Lambda中等待长时间运行的作业完成会增加成本和达到15分钟执行时间限制的风险,应采用异步方法,使用SQS、EventBridge或Step Functions来处理等待。
-
避免依赖可扩展性较差的服务
:选择可与Lambda扩展速度和范围相匹配的服务,如DynamoDB和Aurora Serverless,而不是RDS。
8. 数据库策略
在无服务器架构中,建议使用完全托管的数据库,以匹配Lambda微服务的冗余性、可扩展性和速度。长期以来,DynamoDB是主要选择,但现在也有其他选择,如针对特定用例的专用数据库和更熟悉的关系型数据库Aurora Serverless。传统的关系型数据库如RDS MySQL或Oracle与Lambda搭配时,可能会限制Lambda的功能,削弱无服务器架构的优势。因此,建议提升NoSQL技能,学习将关系型数据模型转换为NoSQL的技术(即非规范化)。除DynamoDB外,还可考虑Neptune、Timestream或QLDB等专用数据库,它们在特定用例中性能更优。如果应用需要关系型数据模型,可使用Aurora Serverless以减少运营开销并匹配Lambda的可扩展性。使用Aurora Serverless版本1时,可考虑使用Data API提高性能。
9. 其他挑战
之前章节已经详细介绍了一些挑战,包括Lambda的大小调整、主动日志记录、集成或契约测试以及估算无服务器架构的云运营成本。
10. AWS中的微服务和API
在Amazon Web Services中,使用托管服务Lambda来托管微服务,它属于函数即服务(FaaS),只需上传函数代码,冗余和扩展等其他方面由AWS完全管理。按请求和函数运行的毫秒数计费,在AWS中,微服务也常被称为Lambdas或Lambda函数。Lambda与许多其他AWS服务紧密集成,如DynamoDB、CloudWatch日志、API Gateway等,访问通常通过IAM策略进行管理。
对于超出Lambda限制的基于容器的微服务,可以使用完全托管的服务Fargate。它适用于长连接等用例,但由于会对空闲时间计费,只有在Lambda不适用时才考虑使用。
11. Lambda的可扩展性和冷启动
将微服务发布到Lambda后,AWS会为每个传入请求提供一个微服务实例,该实例可以是新的,也可以是上一个请求已完成的现有实例。每个实例一次只处理一个请求,多个请求将由多个实例并行处理。默认的Lambda并发限制为最多1000个微服务同时运行,这是一个软限制,可以通过服务请求提高。微服务运行时间越长,达到此限制的可能性越高。
每个启动的实例将保持可用5 - 7分钟,仅对实际执行时间计费。由可用实例处理的请求将有更快的热启动,而新实例处理的请求将有较慢的冷启动。
综上所述,无服务器架构为开发者和组织带来了诸多优势,但也伴随着一系列挑战。通过了解这些技术要点并采取相应的应对策略,能够更好地利用无服务器架构构建高效、可靠的应用。
无服务器架构:技术要点与挑战应对(续)
12. 技术要点总结表格
为了更清晰地总结前面提到的无服务器架构的各项技术要点,下面给出一个表格:
| 技术要点 | 详情 |
| — | — |
| 服务级别协议(SLAs)与多区域部署 | 按使用量计费,多区域部署成本增加不大,提高SLA保障 |
| 无状态微服务 | 不保留过去请求信息,需重新思考应用结构和信息传递方式 |
| 延迟问题及解决策略 | 从代码效率入手,如优化代码、避免大库和框架、使用特定芯片组、基准测试、并行请求等 |
| 完全托管的扩展 | 通过API密钥和使用计划限流,可跟踪用户活动进行计费 |
| 技术成熟度 | 选择模块化库和语言,关注小众库更新和维护,关注服务更新,提改进请求,参与预览版 |
| 服务限制 | 包括内存、代码大小、执行时间、请求和响应大小、存储等限制及对应解决方法 |
| 学习曲线 | 避免微服务规模过大、共享代码、长时间等待、依赖扩展性差的服务 |
| 数据库策略 | 选择完全托管数据库,如DynamoDB、专用数据库、Aurora Serverless等 |
| AWS中的微服务和API | 使用Lambda托管微服务,Fargate用于超Lambda限制的容器微服务 |
| Lambda的可扩展性和冷启动 | 为请求提供实例,并发限制可调整,有热启动和冷启动差异 |
13. 操作流程示例 - 大文件上传
下面通过mermaid格式流程图展示大文件上传的操作流程:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([客户端需要上传大文件]):::startend --> B{请求上传URL}:::decision
B -->|通过API Gateway端点| C(关联Lambda微服务):::process
C --> D(创建并返回签名S3 POST URL):::process
D --> E(客户端通过URL上传文件到S3存储桶):::process
E --> F(客户端提交文件元数据和用户输入到API):::process
F --> G(关联Lambda微服务处理新文件):::process
14. 操作步骤总结 - 应对执行时间限制
当微服务运行时间超过15分钟时,可参考以下操作步骤来应对:
1.
使用Step Functions
- 将应用拆分为多个小步骤。
- 使用Step Functions创建多步骤工作流,在工作流中设置等待、重试和错误处理逻辑。
- 等待过程不会产生费用。
2.
使用SQS或EventBridge
- 微服务启动长时间运行的过程。
- 将任务添加到SQS或EventBridge。
- 微服务终止。
- 在SQS中配置可见性延迟,在EventBridge中安排未来的任务。
- 延迟结束后,触发后续的Lambda继续处理任务。
3.
使用容器
- 若微服务需要超过15分钟的实际执行时间,考虑使用容器。
- 容器没有服务超时限制,可始终运行。
- 若采用事件驱动方法,使用Lambda按需启动容器。
15. 数据库选择决策树
通过mermaid格式的决策树来帮助选择合适的数据库:
graph TD
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([应用需要数据库]):::startend --> B{是否需要关系型数据模型}:::decision
B -->|是| C{是否关注运营开销和可扩展性}:::decision
C -->|是| D(使用Aurora Serverless):::process
C -->|否| E(考虑传统关系型数据库如RDS MySQL或Oracle):::process
B -->|否| F{是否有特定用例}:::decision
F -->|是| G(选择专用数据库如Neptune、Timestream、QLDB):::process
F -->|否| H(考虑DynamoDB):::process
16. 总结与展望
无服务器架构以其独特的优势,如按使用量计费、自动扩展等,为开发者和组织提供了构建高效应用的新途径。然而,其在服务限制、技术成熟度、学习曲线等方面也带来了挑战。通过合理运用多区域部署、优化代码、选择合适的数据库等策略,可以有效应对这些挑战。
在未来,随着无服务器技术的不断发展,相信会有更多的工具和功能出现,进一步降低使用门槛,提高开发效率。开发者和组织应持续关注技术动态,不断探索和实践,以充分发挥无服务器架构的潜力,构建出更加优秀的应用。
超级会员免费看

被折叠的 条评论
为什么被折叠?



