Showing Posts From

Aws

如何理解和应用AI-DLC的开发理念?

很多开发者在使用 Claude Code、Trae 或 Cursor 这类AI开发工具辅助开发时,往往会陷入随性编码(即所谓的Vibe Coding)的陷阱:想到什么,就编写一段简单的提示词让 AI 写什么。这种方式在写功能简单的小应用程序、脚本文件等效率很高,但在面对比较复杂的中大型项目时,很快就会导致代码库混乱、上下文丢失和极高的维护成本。针对以上问题, AWS 在 2025 年初提出并开源了一个核心方法论:AI-DLC(AI-Driven Development Life Cycle,AI 驱动的开发生命周期)。 AI-DLC的概念 在传统的软件开发流程中,整个开发流程的框架总体是由人类驱动的,产品所有者、开发人员、架构师都要将大部分时间花在一些非核心活动上,比如计划、会议和其他软件开发生命周期的事情上,也就是所谓的SDLC(Software Development Life Cycle)。 生成式人工智能技术兴起以后,这类AGI的工具在理解语义、阅读和编写代码的技术与质量得到了突飞猛进的进步,但是如果只是把 AI 当做辅助自动补全和生成代码的局部开发工具,既无法发挥不出来 AI 所具备的强大语义理解和生成的能力,而且容易陷入局部困境,无法适应中大型项目的开发需求。 在这种情况下,ASW 提出了一个针对 AI 时代重构整个软件开发流程和职责的方法论,这就是AI-DLC。这个方法论的核心思想是:在软件开发流程中,重新定义 AI 和人类之间的合作关系,由人类制定判断标准并进行决策,AI 负责流程的编排、执行和自我验证(Humans codify the judgement. AI orchestrates and self-verifies)。 可以通过下表的对比来直观理解软件开发流程在AI时代的范式转变: !AI_DLC_Comparison_Table.png 可以从以下两个维度来理解 AI-DLC的总体逻辑: - 在人工监督下的 AI 驱动执行流程:针对具体的开发需求,由人工智能系统地创建详细的工作计划和流程,并与在人工配合的过程中积极寻求澄清和指导,并将关键决策步骤交由人工判定。这一点至关重要,因为只有人类拥有做出明智选择所需的上下文理解和业务需求知识,AI 工具需要在人工指导和判断的框架下进行工作,而非自行随意发挥。一旦需求澄清和执行方案确认,后续的执行过程完全依赖 AI 工具完成,人工在旁监督即可。 - 动态团队协作:AI 在安装确定的方案执行任务过程中,由人和 AI 所组成的团队在协作空间中团结起来,实时解决问题、进行创造性思维和快速决策。这种从孤立工作到高能量团队合作的转变加速了创新和交付。 AI-DLC的工作流程 总体上,AI-DLC 的开发理念按照如下流程工作:AI 负责按照项目需求制定工作计划,在制定计划的过程中针对需求和技术方案的模糊点向人类提出明确的问题,以寻求更多的上下文和背景信息,最终确定的技术执行方案和行动计划在接受人类验证后开始实施和执行。 !image.png 按照以上整体的理念和流程,AI-DLC 并不是让 AI 在拿到需求以后直接开始写代码,而是强制 AI Agent 遵循一套极其严谨的工程化阶段。它将开发流程分为以下三大核心 Phase。 阶段一:Inception 这个阶段负责澄清需求,制定计划与执行步骤,即解决解决“做什么”和“为什么做”的问题。 该阶段要执行的任务包括: - 工作区检测与逆向工程 (Workspace Detection & Reverse Engineering): AI 首先会扫描现有的代码库,理解当前的架构、技术栈和已有业务逻辑代码。 - 需求分析与用户故事 (Requirements Analysis & User Stories): AI 通过提问并得到明确的答复来澄清模糊的需求,并将其拆解为标准的用户故事(User Stories)。 - 系统设计与工作流规划 (Application Design & Workflow Planning): 确定系统的整体设计架构后,AI 负责将大任务拆分成一个个独立、可并行或串行执行的“工作单元(Units)”。 阶段二:Construction 在此阶段,AI 开始按照 Inception 阶段所制定的计划,逐个处理工作单元(Units)。针对每一个单元,AI 会循环执行以下步骤: - 详细设计: 包括功能设计(代码逻辑)、非功能设计(安全性、性能考量)和基础设施设计。 - 代码生成与测试驱动: AI-DLC 强烈要求代码与测试用例必须同步生成,适应测试驱动开发模式可以有效提升开发质量的管控。 - 自我构建与验证: AI 会尝试跑通构建和并自行执行测试用例,如果报错,它会根据错误日志进行自我修复。 阶段三:Operations 这个步骤是项目开发完成后的上线运维和监控步骤,主要包含开发完成后代码的部署、持续集成以及上线后的监控。AI 同样在这个流程之中协助排查日志、生成运维报告并持续优化。 以上的每个阶段,实际上都可以为下一个阶段的执行提供了更丰富的背景和上下文,从而使 AI 能够提供越来越明智的建议和执行结果。 !image.png AI-DLC理念与最新AI开发工具的对比 以上基于对AWS AI-DLC开发理念白皮书及其相关技术文档的学习,整理了该开发流程和理念的相关理论知识。 但是实际上站在今天(2026年6月)的角度回溯,其实会发现这个AI-DLC的概念并没有什么出奇之处。因为我们现在使用的大多数主流AI开发工具(如Antigravity 2.0、Claude Code、Codex等)在其底层架构设计上已经天然固化并强制执行了以上所描述的核心开发流程和规则。 例如,在使用Google的Antigravity 2.0进行软件开发时,我在一个项目中提出一个开发需求,实际上Antigravity 2.0本身就会在修改任何代码之前首先分析我提出的需求,针对其中的模糊点提出确认,并制定一份implementation plan文档,我确认这个执行计划以后,Antigravity 2.0 就开始执行,并且在执行过程中有必要时申请权限和确认中间步骤,最后在开发完成后还会通过一个walk through的文档总结完整的执行过程。所以以上的这个自动化的过程已经完美的覆盖了AI-DLC的开发理念,而且这还只是Antigravity这类工具的开箱即用的特性而已。 但放在2025年3月份的这个时间节点,在 AI 开发工具的主流还无法应对中大型项目的开发时,AI-DLC 的提出还是很有其价值和应用前景的。而 AI 软件开发工具在2025年后半年在应对中大型项目的开发能力得以突飞猛进,也是因为整个 AI 软件工程界在经历了 2023-2024 年散装 Prompt和盲目写代码导致上下文崩溃的经验教训后,共同走向了使用更规范的流程化的思路来提升 AI 代码质量的殊途同归之路。 以下是 AI-DLC 的开发理念与当前Antigravity 2.0实现的应对与对比: !AIDLC_Workflow_Mapping_20260612.png AI-DLC 理念的价值所在 那么放在2026年的今天来看,在AI开发工具已经越发先进和规范的情况,AI-DLC 及其相关的开发规则和流程还有价值吗? 我认为,无论开发工具如何演化,至少在以下两个方面,这类开发规则依然应该得到重视。 统一团队的开发规则和规范 在团队开发中,不同的开发人员有自己的开发工具偏好,有人习惯用 Trae,有人用 Claude Code,还有人固守 Cursor。不同工具的底层行为差异会导致团队开发代码质量参差不齐。 那么,我们可以定义一套通行于团队内部的类似 aidlc-workflows 这样的显式规则(如 .cursorrules 或全局系统 Prompt),在团队内部就可以跨工具统一 AI 的行为。不管开发人员用什么工具,只要加载了这套统一的开发规则(Rules),AI 都会被迫先写设计文档、先写单元测试,从而实现工程质量的标准化。 !90409f5b-722a-4711-929e-c413f8e3f01e.png Rules 可应对更复杂的多 Agent 协同场景 当前的 Antigravity 2.0 这类开发工具即使到了今天,也依然偏向于使用一个强大的 Agent 解决一个具体 issue 的开发场景。但当我们要面对超大型项目开发和重构时,往往需要产品 Agent、架构 Agent、编码 Agent、测试 Agent 来协同工作。AWS 所提出的这套自适应路由规则(Adaptive Workflow Steering),本质上是为了未来的多 Agent 编排(Multi-Agent Orchestration)搭建的理论框架,不同的 Agent 对应于自己的 Rules,使之工作流程更符合自身角色定义的要求,从而提升各个Agent各自的开发质量。 参考资料 - AI-Driven Development Life Cycle: Reimagining Software Engineering | AWS DevOps & Developer Productivity Blog

Amazon AWS之Cloudfront Service学习总结

Cloudfront的工作流程 Amazon CloudFront Service的定位是 AWS 的全球内容分发网络(CDN)服务(目前已经在所有的AWS Region中处于全面可用/GA状态)。它的核心作用主要是缓存静态资源,通过 AWS 在全球部署的骨干网加速静态以及动态内容的传输与发布。 CloudFront Service的网络底层基于AWS部署的数百个遍布全球的 POP(边缘节点)。这种情况下,当用户或设备向其发起网络请求时,流量会被AWS Anycast 路由到其物理距离最近的节点,极大的加速静态和动态内容的传输。 以下使用一个从 AWS 东京Region的S3 Bucket中通过Cloudfront service下载文件的流程图,来对Cloudfront Service的工作流程进行解释。 终端用户每次向Cloudfront的URL发起请求,该请求首先会被AWS Anycast路由到距离请求发起方最近的Cloudfront网络节点。然后Cloudfront会去检查是否缓存命中(即CloudFront自身的缓存是否包含请求所需要的静态资源文件): - 在缓存命中,即CloudFront缓存包含有请求所需要的文件时,直接跳转到第四步,返回该文件给终端用户。 - 而如果缓存未命中,CloudFront会通过AWS在全球部署的骨干网络向部署在S3东京站的bucket发起回源请求,从S3 Bucket中读取该文件到CloudFront的缓存中,把这个文件返回给终端用户,同时保存在CloudFront的缓存中,这样后续再次访问的时候就可以缓存命中,直接从缓存中向终端用户返回文件。 !35808f53-88a2-425a-b6a0-4085d1b8d8ff.png 由以上流程可以看到,Cloudfront 作为AWS的CDN服务最主要的作用就是:可以实现静态资源文件(尤其是热点资源)的全球网络加速分发服务。热点资源在短时间内请求数量很多,使用CDN服务可以利用其分布在不同地理节点的缓存服务器把资源快速的分发给距离最近的用户终端,既有效的提升了用户体验,而且也避免了所有用户请求集中到同一节点所带来的稳定性和网络路由低效的问题。 即便是针对缓存未命中的动态资源,因为CND缓存服务器(CloudFront)与动态资源实际存储的回源服务器(如以上的东京Region的S3 Bucket)之间走AWS的内部骨干网络,相比用户直接访问回源服务器,用户请求响应的速度也得到很大程度的提升。 CloudFront是如何管理缓存的? CloudFront 不限制存储在其边缘站点的单个文件(对象)的大小,因此可以缓存从几 KB 的脚本文件到几十 GB 的软件安装包。 AWS 拥有遍布全球的多个边缘站点,每个站点都有其特定的硬件存储容量方面的限制,CloudFront 当然不可能在其缓存服务器中一直保存之前访问的缓存文件。 通常情况下,CloudFront 使用最少使用(LRU - Least Recently Used)的算法来动态管理其缓存服务器中所保存的文件。如果一个文件在某个边缘站点存储时间很长且很少被访问,当前存储空间不足时,它就可能会被删除以腾出空间。这样的话,下次对这个文件发起的新请求又会被转发到回源服务器请求数据。 当然除了以上的 LRU 算法以外,缓存是否失效也与文件自己设置的 TTL 生命周期时长有关。 缓存时间限制TTL 文件在 Cloudfront 缓存中的有效时间也可以通过源站点的 TTL 参数来进行设置。 默认情况下,CloudFront 会遵循源站点(如 S3、EC2 或 API Gateway)返回的 HTTP 缓存标头参数Cache-Control: max-age=和Expires: 来设置该文件在缓存中的有效时间。 因此,如果我们对于文件的时间有效性有特定的要求,可以在源站服务器配置或 S3 对象元数据中设置这些标头信息,以更精细地控制每个文件的缓存时间。 高 TTL (缓存时间长): - 优点:可增加缓存命中率。文件在边缘站点保留时间长,意味着当用户请求时,更有可能从边缘站点直接服务,从而大幅减少回源请求,这就减少了从源站到 CloudFront 的数据传输费用。 - 缺点:内容更新较慢,用户请求到的文件可能是过期的,因此如果对于文件本身的生命周期有较高要求,不应设置过高的TTL。 低 TTL (缓存时间短) 或 0 TTL (不缓存): - 优点:每次请求得到的数据文件的内容都是最新的。 - 缺点(更贵): 会降低缓存命中率,这样大量用户请求会到回源服务器请求数据,请求数量和费用增加。 因此,究竟应该要设置高还是低 TTL 参数,要根据自己文件和应用的设计需求来定:如果对数据文件内容的时效性要求比较高,就应该选择低TTL,代价就是费用会较高,否则就应该选择高TTL的设置,尽可能减少回源请求的次数。 Cloudfront的费用模型 以下通过从S3上下载文件的典型应用对比增加CloudFront的情况下,对于云服务使用成本的影响。 总体来讲,对从S3上下载文件的这个流程,与云服务使用成本费用相关的部分主要包含:存储、出向流量、请求(API/HTTP)。 - 存储 (Storage):即 S3 上的静态对象存储费,按存储在 S3 中的数据量 (GB/月) 计费。Standard 存储类前 50 TB:0.09 / GB。 - Cloudfront 下载模式,按地区+阶梯计费。北美/欧洲环境中的费用为 0.0004 / 1,000次请求。 - CloudFront 模式下,如果缓存未命中,从 Cloudfront 向 S3发出的 API 请求费与以上相同。因此这部分费用与缓存命中的比例相关。高命中率下这项费用趋近于 0。 - CF HTTP/HTTPS 请求费:按用户发送给 CloudFront 边缘节点的请求次数计费。HTTPS 请求在北美的费用为 0.0004 / 1,000次请求。 - 而通过Cloudfront下载,这部分费用包含两个部分,一个是用户发起的Cloudfront API的请求费用,费率15 固定费用的 Pro 用户为例,该套餐包种包含的免费额度包括: - 出向数据流量传输 : 高达 50 TB,这部分按照传统按需模式下的价值约 $4000+。 - 访问请求数: 10,000,000 次(1000 万次)。 - 增值安全 (免费送): 强制开启并包含 AWS WAF(Web 应用防火墙),自带 25 条规则,并包含 DDoS 保护。 - S3 存储抵扣: 每月额外赠送 50 GB 的 Amazon S3 标准存储额度。 !ae7f5972-7413-4337-8b34-9eb8adfd1f54.png 在这个固定费率方案的加持下,使用CloudFront的费用成本将会大幅度降低,以下是一个S3存储容量1TB,每月出站流量10TB,请求数量1000万次,缓存命中率90%的情况下,对比直接访问S3、通过CloudFront访问S3(标准费率模式)、通过CloudFront访问S3(固定费率模式)这三种情况下的费用状况对比: !21d886b9-5247-41e0-b905-17fc1aed910a.png 参考资料 - https://aws.amazon.com/cn/s3/pricing/ - Amazon CloudFront CDN — 计划和定价 — 免费试用 - CloudFront 固定费率定价方案 - Amazon CloudFront

案例解析Gitops驱动AWS云原生应用的开发与部署流程

本文通过一个简单的Python项目演示在AWS中基于Gitops的理念进行代码开发、测试和生产环境的自动化部署的完整流程。 该案例的大致需求是: - 在本地客户端上通过HTTP发出请求(请求消息中包含了一个文件名字符串)给AWS API Gateway; - AWS Gateway收到以后转发给Lambda; - Lambda在S3中根据文件名创建一个文件并给客户端返回消息。 1.Gitops进行云原生应用的开发流程简介 在传统的运维模式中,我们习惯于使用命令式操作来进行云端环境的运维和管理工作(例如在AWS的web console页面中手动输入命令来创建 S3 桶,或手动打包代码上传到S3中等)。而在当前日益流行的 GitOps 的理念下,将基础设施即代码 (也就是所谓的IaC,Infrastructure as Code) 与 CI/CD 流水线深度结合的方式,可以让运维工作更加高效和可靠。 Gitops的核心思想非常简单:项目代码的 Git 仓库是系统状态的唯一真实来源,云端环境的部署以 Git 仓库中提交的代码为基础自动展开。 !image.png 这套标准化的开发与测试流程如下: 1. 编码与测试环境:开发人员在本地 IDE 中编写业务代码(Python、Java、Node.js等)和基础设施架构的定义文件(YAML),并在本地利用使用单元测试工具(例如Python的 pytest )跑通基础单元测试。 2. 代码提交 (Git Push):开发人员将代码推送到 GitHub 的 main 分支上。 3. Github 流水线与自动化测试:前一步的代码推送自动触发 GitHub Actions 流水线。Actions 收到代码提交后基于最新代码拉起隔离的容器环境,安装其中定义的 pipeline 的配置文件进行依赖安装与单元测试。如果这个自动化流程中执行的测试失败,流水线直接红灯阻断报错,防止错误代码污染云端。 4. AWS 云端自动编排 (SAM & CloudFormation):以上的测试流程通过后,Actions 继续基于严格的权限控制(OIDC),自动调用 AWS 的云端基础设施部署接口(Cloud formation),这个过程中会执行代码编译、打包,并将基础设施平滑部署到 AWS 环境。 通过这种的这种高度自动化的方式,可以彻底消除环境差异。开发人员只需专注写代码,剩下的工作全交给流水线来完成。 2.本地环境以及代码结构准备 以上的 Gitops 流程的实现,需要首先将项目从本地联调模式升级为生产环境部署模式。对应于以上流程的一个标准化的Python工程目录树应该如下所示: 其中的 template.yaml 文件是AWS CloudFormation的基础设施模板定义文件,可以认为是该项目向 AWS 提交的建筑施工图纸。具体内容在后续的AWS CloudFormation 的执行流程环节详细介绍。 其中的 .github/workflows/pipeline.yaml 文件中定义了Github Actions CI/CD 流程的自动化执行规则,在后续讲解Github的Actions执行流程中详细介绍。 src/app.py 是该Demo在AWS Lambda中执行的核心业务逻辑代码,最终这个代码会被部署到AWS的 Lambda 中。需要注意,在生产环境中,Lambda 必须包含完善的错误捕获、CORS 跨域支持以及结构化日志。 这部分的代码如下:主要的流程就是对API Gateway 发过来的请求消息进行解析,取出其中的filename字段,然后在S3中创建一个文件。 后续要在 Github Actions 定义的CI/CD流程中执行自动化测试,在此就需要提前写好单元测试的代码,该案例的单元测试的代码在 test/test_app.py 中: 代码提交后,在Github Actions的流水线在AWS的cloudformation中执行具体的部署之前, Actions 会先运行以上的这段测试代码。如果测试不通过(如断言失败),程序会抛出非零退出码,流水线会自动触发以阻断代码在生产环境中的发布。 3. AWS OpenIDC角色设置 OIDC (OpenID Connect) 是一种基于 OAuth 2.0 的身份认证协议。当Github的流水线运行时,GitHub 会给当前的 Runner 颁发一张带有数字签名的临时数字身份凭证 (JWT Token)。Runner 会基于这个凭证访问 AWS 。AWS 验证签名发现确实是 GitHub 颁发的,并且确认了来访者是指定的那个仓库的 main 分支,就会给 Runner 发放一组有效期极短(通常为 1 小时)的临时开门权限,用完即废。这就彻底消灭了需要手动管理的长期密钥,实现了真正的零信任和自动化安全。 要实现以上描述的这个机制,需要完成三步:在 AWS 里告诉它信任 GitHub、在 AWS 里创建一个专属角色、在 GitHub 流水线里设置为OpenIDC登录方式。 首先,在 AWS 中将 GitHub 注册为“受信任的身份提供商”。 登录 AWS 控制台,进入 IAM 服务,在左侧导航栏选择身份提供者 (Identity providers),然后点击 添加提供商 (Add provider),并选择 OpenID Connect,填写以下信息后点击添加提供者: - 提供商 URL (Provider URL): https://token.actions.githubusercontent.com - 受众 (Audience): sts.amazonaws.com 其次,在 AWS 中创建一个供 GitHub 扮演的 IAM 角色 (Role)。 在 IAM 左侧导航栏点击 角色 (Roles),然后点击 创建角色 (Create role)。按照下图进行填写和选择: !dbefdaa7-e601-4a2a-866e-fb460c90437e.png 接下来要对这个角色添加权限 (Add permissions):为了后续的CI/CD流程中让 SAM 能顺利部署资源,此处赋予 该角色AdministratorAccess权限。最后把该角色命名为 GitHubActionsDeployRole并创建角色即可。 以上的角色创建后,进入该角色的详细信息页面,记录下其ARN,后续需要配置在Github Actions所要求的pipeline.yaml文件中: !11e67041-bc7c-4255-b8ce-8a21a9d8492c.png 现在AWS中要进行的配置和修改就结束了,下一步需要在Github Actions的流水线配置文件中进行配置。 4. Github的Actions执行流程 那么Github的Actions究竟是如何启动并执行自动化的CI/CD流程的?答案是基于代码提交的.github/workflows/pipeline.yaml 文件。当开发人员在本地执行 git push 时,GitHub Webhook 会自动触发此文件来执行完整的 CI/CD 流水线。 Github Actions 背后的工作逻辑是:Github的后台引擎只会监听项目根目录下的 .github/workflows/ 这个文件夹中的yaml文件(只要后缀是 .yml 或 .yaml 即可),可以有多个流水线并行工作。该目录下的yaml配置的文件名可以自定义,所以在真实的商业项目中,通常会在 .github/workflows/ 目录下放多个文件,各司其职。例如: - unit-test.yaml:定义只要提交代码(无论什么分支),就会运行 Python 单元测试。 - deploy-prod.yaml:定义只有当代码推送到 main 主分支时,才执行部署到 AWS 云端的全套动作。 在对这个yaml配置文件的解析中,GitHub 会自动根据文件里 on: 关键字定义的条件,决定唤醒哪个流水线。 对于当前的这个demo项目而言,其对应的pipeline的yaml配置文件为: 4.1 Actions判断单元测试 问题:每次我们把代码推送到Github以后,Actions是如何判断要执行哪些单元测试文件的,以及如何判断单元测试执行成功的? 对应以上的第一个问题,Actions判断要执行的单元测试的内容由其pipeline的yaml文件来限定,对于这个demo就是上面的: 也就是,当前demo要做的单元测试就只有test下的test_app.py这个源文件。如果给 pytest 指定的不是单元测试文件,而是一个目录的话,pytest 会向下递归搜索该目录中所有的 Python 文件,但它只认文件名以 test_ 开头(如 上面的test_app.py)或以 _test.py 结尾的文件,并只运行其中名字以 test_ 开头的单元测试函数。 对于上面的第二个问题,Actions 判断单元测试是否成功的标准与单元测试文件中的assert语句相关。当assert语句中指定的条件成立的话,表示单元测试运行正常,继续往下执行,直到完整的单元测试流程执行完毕,并向系统返回退出码 0 表示整个过程顺利完成;如果有一个assert语句的条件不成立,程序会抛出AssertionError 异常,并返回退出码 1 。 GitHub Actions 中的操作系统对每个执行步骤的退出码进行检测,如果退出码为 0 表示该步骤顺利完成,否则会立刻判定当前步骤执行失败,并阻断后续所有命令的执行,返回错误。 5. AWS CloudFormation执行流程 在 CI/CD 流程中,基础设施即代码 (IaC) 的核心思想是:所有的云资源都应该由代码定义和自动创建,而不是人工去 AWS 控制台点选。而这部分工作就由 template.yaml 文件来进行定义。 在前面 Github Actions流水线配置文件.github/workflows/pipeline.yaml 中,最后一步执行的这个命令sam deploy --stack-name my-iot-edge-stack命令就负责基于template.yaml 文件把该文件中定义的AWS云端基础设施落实在云端的环境中。 - sam deploy 读取 template.yaml 配置文件,将该配置文件以及完整的部署包,通过 OIDC 获取的临时权限,发送给 AWS 底层的一个核心服务——AWS CloudFormation。 - CloudFormation 收到以上配置文件后,会自动计算出需要执行哪些底层 API 来按顺序创建 S3 Bucket、Lambda和 API Gateway。 - 这个自动部署的过程,如果有任何一步失败,CloudFormation 会自动回滚(把已经建了一半的资源全删掉),保证云端环境永远不会处于“半残废”的脏状态之下。 该demo对应的template.yaml如下所示: 问题:如果后续开源人员对当前的代码进行修改,每次修改以后提交到Github上,它都会执行自动部署的pipeline去创建S3 Bucket、Lambda Function以及API Gateway。那么如果之前的提交已经创建过了这些资源的话,会发生什么事情? 答案是:无论以上的流水线执行多少次,云端最终的状态都只会和云端环境部署代码里声明的状态保持一致。 在 Actions 流水线第一次运行 sam deploy --stack-name my-iot-edge-stack时,AWS CloudFormation 会在云端创建了一个名为my-iot-edge-stack的“逻辑档案袋”。 !0ab67a79-aa9d-4eb7-a70b-e6549873cf97.png 这个档案袋里记录了该流水线创建的的 S3 Bucket、Lambda、API Gateway 的所有当前状态和唯一 ID,而且AWS 牢牢记住了这些资源与该流水线之间的关联关系。 后续修改了代码并再次推送时,流水线会把新的图纸和代码打包发给 AWS,AWS 收到后不会立刻去覆盖,而是根据具体的情况分别进行处理: - 如果只修改了业务代码 (如app.py):也就是说template.yaml 的内容没有发生变化(即不需要动基础设施),只有 Lambda 的底层压缩包哈希值变了。此时,AWS 只会把新的代码包部署到现有的 Lambda 函数上,替换掉旧代码。之前的 S3 Bucket 和 API Gateway 完全不会被触碰,S3 里的历史文件也完好无损。 - 修改了基础设施参数 (template.yaml):例如把Lambda Container配置的 MemorySize: 128 改成了 MemorySize: 256。此时AWS 的判断是Lambda 的配置属性发生了变化。它会通过底层 API 直接修改现有 Lambda 函数的配置,将其内存扩容至 256MB。同样,S3 和 API 保持原样。 - 什么都没改,不小心又触发了流水线:即新代码和档案袋里的状态 100% 一致。那么 Github Actions 流水线会在 sam deploy 这一步直接输出 No changes to deploy. Stack my-iot-edge-stack is up to date,然后以绿色的成功状态秒级结束,不会做任何多余的操作。 以上流程中需要注意的是,S3 Bucket 是用来存核心业务数据的,CloudFormation 对存储类资源有特殊的保护逻辑。如果某次提交的 template.yaml 里把 IoTDataBucket 这一大段代码直接删除了(或者给它改了名字),然后推送到 GitHub。流水线去更新时,AWS 默认是不允许直接删除带有数据的 Bucket 的,这会导致部署直接报错 (Update Rollback),从而保护生产数据不被一次手滑的 Commit 删光。 6.测试验证 经过以上完整的准备工作以后,提交代码到Github的main分支上,其对应的Actions会自动启动,执行其中的单元测试,并且在单元测试通过以后自动在AWS上部署云端环境: !f7a8a8b2-6abb-43f9-b885-fa562efa483c.png 整个过程结束以后,就可以在 AWS Lambda中查看具体的部署情况及其对应的API: !dab16dbf-a3de-4640-917d-fd704f430e06.png 接下来就可以在terminal等终端上通过curl命令进行测试了(需替换成自己的API):

Amazon AWS之Lambda Service学习总结

AWS的 Lambda Service是一种全托管的无服务器(Serverless)计算服务。相比于传统的基于 EC2 和常驻进程的 Java/Python/Node.js 服务,在相同的应用需求下使用 Lambda,开发人员只需要上传 Java、Python 或 Node.js 代码到服务器上,AWS 就会自动准备计算所需要的资源,并在代码执行完毕后立即释放。本文对 AWS 的 Lamda Service 的各种概念进行了总结。 1.AWS Lambda Service介绍 在传统基于 AWS EC2 和的常驻进程的 Java/Python/Node.js 后台服务架构中,我们的研发和运维模型是面向服务器的,也就是说,运维人员需要时刻关注操作系统的安全补丁、JVM 虚拟机运行中的调优、自动负载均衡器(ALB)的配置,以及为了防范突发流量而不得不预留的大量冗余算力。这些计算资源在夜间往往处于极度低效的闲置状态(通过自动负载均衡可以缓解但是无法解决问题),从而造成了巨大的云账单浪费。 AWS Lambda 是亚马逊云科技推出的一种全托管的无服务器计算服务。它的出现,从根本上改变了后端的计算范式:运维人员只需要上传代码(可支持 Python, Node.js, Java, Go, 甚至是基于容器镜像的自定义 Runtime),AWS 就会在毫秒级的延迟时间内自动准备好执行环境,而且在代码执行完毕后立刻释放资源。这种模式既规避了繁琐的运维任务,又可以自动完成计算资源的启动和释放,真正实现按需付费。 !image.png Lambda 核心理念一:事件驱动 Event-Driven 在 Lambda 的世界里,不再有类似 Tomcat 或 Netty 那样一直阻塞监听 HTTP 端口的常驻守护进程。Lambda 的生命周期完全是由事件(Event)唤醒的,这个事件也就是 Lambda 语境中的触发器 Trigger。例如以下是一些摄像头/IoT领域的典型事件/触发器: - 边缘安防摄像头通过 MQTT 协议向 AWS IoT Core 发送了一条越界检测告警的告警消息。 - App 客户端通过 Amazon API Gateway 发起了一次获取设备历史录像列表的 REST API 请求。 - 端侧设备将一段异常运动轨迹的短视频切片成功上传到了 Amazon S3 存储桶。 只有当这些确切的事件发生时,Lambda 才会被拉起执行其对应的代码,并且计费精确到毫秒级别。这意味着当设备全部处于静默期时,云端的计算节点账单将会瞬间归零。 Lambda 核心理念二:无状态 Stateless 这是与传统的基于 EC2 常驻进程的 Java/Python 等后台开发模式差异最大的部分。 由于 Lambda 实例是按需创建且随时可能被销毁的,因此,在 Lambda 的执行函数中绝不能在代码的本地内存或磁盘目录(如 /tmp)中保存任何需要跨请求复用的会话(Session)或业务状态数据。 所有持久化的业务状态,必须被外置化,例如写入到 Amazon DynamoDB(NoSQL 键值存储)、Amazon RDS(关系型数据库)或 Amazon S3 中。 在基于 AWS Lambda 进行 Serverless 服务的网络架构设计中,首先必须牢记并且基于 AWS 官方设定的一些硬性天花板参数来进行服务的设计与构建: - Lambda 服务函数的最大执行时间 (Timeout): 目前为15 分钟(900 秒)。因此,Lambda 绝不适合运行长时间的后台批处理任务,长时间的处理任务可以使用 AWS Fargate 或 AWS Batch。 - 内存与算力配比: Lambda 函数运行的内存配置范围从 128 MB 到 10,240 MB,无法直接选择 vCPU 的核心数,AWS 规定 vCPU 和网络吞吐量与分配的内存大小成正比例线性增加,所以内存的配置直接决定了存储和计算资源。 - 有效载荷 (Payload): 同步调用的请求体中所包含的 Payload 上限为 6 MB,异步调用则为 256 KB。 2.AWS Lambda的工作流程详解 Lambda 在 AWS 系统中的具体实现,采用了类似于 Docker 容器的方式为不同用户的不同应用程序创建独立的运行空间。只不过,为了兼顾公有云下多租户环境下的极致安全隔离,以及无服务器计算所要求的极速启动,AWS 使用 Rust 语言从零开发并开源了所谓的 Firecracker 技术。这是一种基于 KVM 的微型虚拟机(microVM),相较于共享操作系统内核的传统容器,Firecracker 能在几十分之一秒内拉起一个具备完全硬件隔离级别的微型沙箱。简单的理解,就是一种更高级、性能更好的容器。 当我们把代码(例如一段 Python 3.12 写的设备鉴权脚本)部署到云端的 Lambda 环境中,其底层的真实生命周期如下图所示: !be207b75-f9a8-464d-ab69-00110c159d1d.png 由此可见,Lambda容器的运行过程主要可以分为以下三个阶段: - Init (初始化阶段 - 冷启动): 当第一个请求到来,或者现有的实例都在忙碌,AWS 会新分配一个 Firecracker 实例。该实例启动后,首先通过内网从 S3 下载部署包,启动 Python 解释器,并执行Lambda 函数文件除了 def handler(event, context): 以外的所有全局代码(例如 import boto3,或建立数据库连接)。这个阶段非常耗时,被称为冷启动(Cold Start)。对于沉重的 Java JVM 来说,这个阶段甚至可能高达数秒。 - Invoke (调用阶段): AWS 将 HTTP 或者 MQTT 消息的 JSON payload 传递给 Lambda 的 handler 函数并执行其业务逻辑。 - Freeze & Thaw (冻结与复用):handler 函数 return 之后,AWS 并不会销毁这个 Firecracker 实例。相反,它会将这台微型虚拟机的 CPU 挂起(仍然存活在内存中)。此时实例不产生任何计费,但内存中的状态(包括数据库的 Connection 对象)被完整保留。如果短时间(通常 5 到 15 分钟内)有新请求涌入,AWS 会瞬间解冻该实例,跳过 Init 阶段直接进入 Invoke(也就是直接执行 handler 函数)。这就是极速响应的暖启动(Warm Start)。 优化Cold Start问题的Provisioned Concurrency机制 需要注意,以上提到的暖启动的流程,Lambda 的响应速度会非常快,但是如果是冷启动的话,整个容器启动、加载并运行的过程就会比较长,在某些应用场景下,会造成很糟糕的用户体验。为了解决这个问题,AWS 官方推出了 Provisioned Concurrency (预配置并发) 机制。它的核心逻辑是用空间换时间。 在流量真正到来之前,可以通过 API 指令让 AWS 在后台静默分配指定数量的微型虚拟机,并提前跑完耗时的 Init 阶段。这样当真实的设备并发请求进入时,所有的请求将直接被路由到这些已经预热完毕的实例上,这样就可以实现两位数毫秒级的极致响应速度。 但值得注意的是,开启预配置并发后,哪怕没有任何请求,也要为这些处于预热状态的实例按时间持续付费。 这种模式比较典型的应用场景就是,预先识别自己的应用在每天的哪些时间段会出现访问的高峰阶段,然后每天固定在这个时间段来临之前通过开启这个Provisioned Concurrency机制来提升用户访问响应的速度。 3.AWS Lambda Trigger的触发消息队列模式 如上所述,Lambda 仅仅只是计算单元,在真实的业务场景流转中,如何将设备端所发出的请求数据平滑、安全、可靠地路由给 Lambda?根据不同的业务场景,AWS 提供了以下三种截然不同的调用模型(Invocation Models): !7d870224-20f9-4a02-babe-610fcd072937.png 同步调用模式: - 工作机制: 客户端发起请求后,会阻塞连接,直到 Lambda 执行完毕并返回 HTTP 响应。 - 队列特征:在该模式下没有任何内部队列缓冲。 因此如果瞬间涌入 5000 个请求,而当前的 Lambda 并发配额仅为 1000,那么多出的 4000 个请求会立即被系统拒绝,并向前端设备返回 429 Too Many Requests (ThrottlingException)。 - 应对策略: 前端设备的请求必须实现严谨的带抖动的指数退避重试算法。 异步调用模式: - 工作机制: 遵循即发即弃原则。AWS IoT Rules Engine 将事件推送到 Lambda 的内部网关后,立刻收到确认,并将事件放入一个托管在 AWS 内部的队列中,此后 Lambda 从这个队列中异步拉取并执行。 - 队列重试与 DLQ: 如果 Lambda 代码执行中抛出异常,或者遭遇并发限流,Lambda 内部队列默认会重试最多 2 次(时间间隔通常为 1 分钟和 2 分钟)。需要注意: 如果这两次重试均失败,消息将被永久丢弃,所以本质上这个队列机制是不可靠的。因此,为了保证告警或重要信令的不丢失,必须为该 Lambda 绑定一个 Dead-Letter Queue (DLQ,死信队列),通常指定一个 Amazon SQS 队列来捕获最终失败的消息,以便后续告警分析或人工介入补偿。 流式队列触发: 如果端侧设备发出数据的频次很高,由 Lambda 来处理这类高频消息并非是一个良好的设计。 - 合理的设计架构是将 IoT Core 等发的高频消息通过路由先接入 Amazon Kinesis Data Streams 或 Amazon SQS。Lambda 不作为独立的 HTTP 终点,而是运行一个后台轮询器。然后这个轮询器在执行中会根据设定的 BatchSize 和 MaximumBatchingWindowInSeconds(例如:最多等待 1 秒或攒够 500 条记录),将零散的流式数据打包成一个 JSON 数组,然后塞给一个 Lambda 实例处理。 4.Lambda开发和部署的最佳实践 在真实的 IoT 云后台原生开发中,无论是通过 AWS 网页控制台手动修改代码,还是允许开发工程师在本地电脑直接拥有生产环境的部署权限,都是极其危险的。更合理的做法是在团队内部推行基础设施即代码(IaC),并建立严格的 CI/CD 自动化部署流水线。 实际上 AWS 专门开发了一个SAM (Serverless Application Model) 工具用于处理 Serverless 云服务的开发与标准化部署的流程。 对于 Lambda 服务而言,其开发和部署的最佳实践流程大体可以分为以下5个阶段: - 本地 IDE 与代码定义:开发人员在本地 IDE 中不仅要编写 Python 业务逻辑(app.py),还要负责维护一个 template.yaml 配置文件。在这个 YAML 文件中,需要以声明式的方式定义所有的云资源。这个配置文件也就是云端进行部署的系统图纸,这保证了云上环境的绝对可追溯性和不可变性。 - 打包构建 (sam build):用于生成交付物,最终所有的代码和依赖会被归档整理到一个名为 .aws-sam 的本地隐藏文件夹中,准备上云。 - 云端同步 (sam deploy):在这一步,SAM 会自动把刚才打包好的代码和依赖压缩成一个 .zip 文件,然后通过安全通道,将这个 ZIP 包上传到 Amazon S3的一个隐藏存储桶中。 - 编排与部署:前一步上传的不仅是代码 ZIP 包,还包括被翻译过的 template.yaml 文件。AWS 会将这个配置文件交给 AWS CloudFormation(AWS 的基础设施自动化编排引擎),Cloudformation 基于 template.yaml 文件进行云端环境的实际部署。 - 触发执行:完成上一步实际上就已经部署完成了,接下来就可以通过客户端向服务端发出消息进行功能的测试与验证了。 在具体的工程实践中,以上的流程应该与 CI/CD 自动化测试和部署流水线相结合,在软件的整体发布流程上可以做得更加科学和高效:工程师写完 Python 代码和 template.yaml,提交(Git Push)到代码仓库(如 GitLab、GitHub 或 AWS CodeCommit),触发一条自动化的 CI/CD 流水线,由云端的服务器自动执行 sam build 和 sam deploy,经过严格的自动化测试后再发布到线上。 !AWS-SAM-CICD-Pipeline.png 参考资料 - The Ultimate Guide to AWS Lambda | Serverless Framework | Serverless Framework

Amazon AWS之Bedrock Service学习笔记

AWS Bedrock的核心功能列表 Amazon Bedrock 是 AWS 提供的一项全托管的 Serverless 服务,能够支持通过统一的 API 访问来自各个领先 AI 公司(如 Anthropic, Meta, Mistral, Amazon 等)的高性能基座模型 (FMs,Foundation Models),方便提供构建生成式 AI 应用的一系列周边功能。 !image.png 以下是 Amazon Bedrock 提供的核心功能模块列表: - 针对基础模型 API (Foundation Models) 提供统一的 Serverless API接口,用于访问业界领先的多模态大模型(包括 Anthropic/Meta/Mistral/Cohere/AI21 Labs 以及 Amazon 自家的 Titan 和 Nova 模型,也包括国内的Deepseek/GLM/Qwen/Kimi等模型)。而且允许用户的应用调用跨多个 AWS 区域动态路由模型推理请求,从而提高可用性并突破单一区域的吞吐量限制。 - 支持原生的知识库应用和全托管的 RAG(检索增强生成)管道,能够自动连接后端数据源(如 S3、Confluence、SharePoint 等),处理文档分块切片,将其转换为向量存储在 OpenSearch 等向量数据库中,并在用户提问时自动进行相似度检索和上下文增强。 - 可支持模型微调 (Fine-tuning),允许使用企业自有的标注数据对部分支持的模型(如 Amazon Titan、Llama、Cohere 等)进行有监督微调,以提升模型在特定领域的准确性。 - 基于安全护栏 (Guardrails)实现独立于模型的安全过滤层,可支持自定义主题拒绝策略,用于对模型生成内容过滤有害信息(仇恨、暴力、性)、拦截越权提示词(Prompt Injection),以及脱敏 PII(个人敏感信息),以确保 AI 输出符合企业合规要求。 Amazon Bedrock与Sagemaker、Q之间的关系与区别 在Amazon AWS 的 AI 生态中,Amazon Bedrock、Amazon SageMaker 和 Amazon Q 这三个服务的定位从表面看起来都是提供了 AI 模型访问方向上的支持,其定位和使用上的差异很容易让人感到困惑。在此对这三个服务在具体使用中的定位进行详细解释。 1. Amazon Q:其定位是开箱即用的企业级定制版本的AI 助手 - 本质上就是完全构建好的、直接面向最终用户和开发者的、企业化定制版本的生成式 AI 助手。 - 其核心特点就是不需要写任何代码就可以直接调用模型,开通即用。可分为几个不同的版本: - Amazon Q Developer (前身为 CodeWhisperer): 主要用于嵌入在 IDE (如 VS Code) 或 AWS 控制台中,辅助写代码、排查 Lambda 报错、或者解释一段复杂的 IoT Rule SQL。 - Amazon Q Business: 可以认为是面向企业内部员工的企业知识库,可以把公司内部的 HR 文档、IT 规范等文档接入进去,员工就可以直接通过 Q Business 所提供的网页端进行问答,自带了严格的权限控制(即只回答员工有权限看的内容)。 - Amazon Q开通以后是按照人头收费的,例如 Amazon Q Business 的 Pro 订阅大约是每个用户每月 20 美元。这样也就意味着它的定位是面向企业内部(To-B/To-E)或开发者个人的效率工具,不适合直接集成给 C 端消费者(To-C)使用。 1. Amazon Bedrock:其定位是大模型 API 的超级网关 (PaaS for GenAI) - 该服务是面向应用开发者(Backend/Full-stack Engineers)的完全托管 Serverless 生成式 AI 服务。 - 其核心理念就是开发人员不需要自行部署模型,也不需要管理服务器,只需要一行代码(调用 API),就能切换使用多个业界顶尖模型。因此,在 AWS 生态中,Bedrock 是开发人员构建自己的 AI 应用的基石,为AI 应用提供模型服务(MaaS)。 1. Amazon SageMaker:其定位是为机器学习模型开发和训练提供的云端支持平台(End-to-End MLOps PaaS) - 该服务是面向模型开发者(数据科学家和算法工程师)的全链路机器学习工作台。 - 使用 SageMaker 进行机器学习AI模型的开发和训练,需要开发者选择具体的 EC2 实例类型(如 ml.p4d.24xlarge),配置 Jupyter Notebook,并编写模型训练脚本(PyTorch/TensorFlow)。 - Sagemaker 不仅可以用于开发和训练生成式 AI 大模型,更可以广泛用于传统的预测性 AI(如 XGBoost、时间序列预测等)。 - 因此如果业界开源的 AI 模型无法满足具体的应用的需求,开发者可以自行开发模型的网络架构,并收集大量的训练数据从零训练或对现有模型进行深度微调,在这种情况下就应该使用 SageMaker。 下图总结了三者在定位上的差异: !AWS_AI_Architecture_%281%29.png Bedrock模型的基本使用测试 在使用代码对 Bedrock 上模型进行实际的调用测试之前,首先需要安装本地环境中的依赖包并做适当的配置。在当前系统(Windows)的终端窗口输入以下命令安装AWS CLI v2:(首次安装后需要重新进入终端才能使用aws cli命令) 首次使用AWS Cli工具时,需要先在 AWS 的web console(IAM-用户/[用户名]/安全凭证/访问密钥)中创建一个新的访问密钥,并在终端中使用aws configure命令把这个密钥配置进去: 如果要查询 AWS Bedrock 指定region所支持的model列表及其对应的 modelArn,使用以下命令: 以下使用Python基于AWS的boto3 package完成一个访问Bedrock指定模型的例子: 可以看到访问Bedrock Model的流程跟使用HTTP访问各个大模型服务的API接口没有太大区别,只不过这里是使用AWS Boto3的bedrock_runtime.converse接口并指定modelId而已。