对于今天的开发者、架构师和技术爱好者而言,云计算早已超越了简单的"虚拟机租赁"或"服务器托管"阶段。它已经演化为一套丰富、强大且精密的工具集,能够以前所未有的方式设计、部署和扩展应用程序。真正的云原生思维,是掌握并运用多种架构模式,为不同的业务场景选择最合适的解决方案。
我整理了三个具体的、可动手实践的项目,一步步构建出功能完备的解决方案:
弹性单体架构:学习如何利用基础设施即服务(IaaS)的控制力,同时结合托管服务的可扩展性与持久性,构建一个既健壮又易于管理的个人云存储系统。
无服务器****API:拥抱事件驱动的函数式编程模型,彻底摆脱服务器管理的束缚,构建一个能够自动、海量扩展的动态应用程序接口。
全球边缘网络:探索如何通过去中心化的全球网络优化内容分发,为用户提供极致的访问速度和坚固的安全防护。
新用户可获得高达 200 美元的服务抵扣金
亚马逊云科技新用户可以免费使用亚马逊云科技免费套餐(Amazon Free Tier)。注册即可获得 100 美元的服务抵扣金,在探索关键亚马逊云科技服务时可以再额外获得最多 100 美元的服务抵扣金。使用免费计划试用亚马逊云科技服务,最长可达 6 个月,无需支付任何费用,除非您选择付费计划。付费计划允许您扩展运营并获得超过 150 项亚马逊云科技服务的访问权限。
1. 弹性单体架构 ------ 使用亚马逊云科技 EC2 与 S3 构建可扩展的个人云盘
在云架构的演进过程中,并非所有应用都需要被重构为复杂的微服务。许多成熟的、功能强大的单体应用依然是业务的核心。本教程将以一个广受欢迎的开源项目NextCloud为例,展示如何将传统的单体应用部署在云上,并通过巧妙的架构设计,赋予其云原生的弹性、持久性和可管理性。构建一个功能强大的个人云盘,但更重要的是,掌握一种核心的架构模式:计算与存储的分离。
1.1 解决方案架构:计算与对象存储的协同效应
目标是部署NextCloud应用,但其核心架构思想在于,不会将用户上传的文件直接存储在运行应用程序的服务器的本地磁盘上。取而代之,配置NextCloud,使其将所有数据无缝地存储到亚马逊云科技 Simple Storage Service (S3) 中。
这种设计的架构图如下所示: 用户 -> 互联网 -> 弹性IP (Elastic IP) -> 亚马逊云科技 EC2 实例 (运行NextCloud应用逻辑) -> IAM 角色 -> 亚马逊云科技 S3 存储桶 (存储用户文件)
这种模式常被称为"弹性单体"(Resilient Monolith)。它保留了单体应用易于部署和维护的优点,同时解决了传统单体架构最棘手的两个问题:
- 数据持久性与扩展性:服务器实例可能会因为硬件故障、软件错误或维护而终止,其本地存储(如亚马逊云科技 EBS卷)上的数据也面临风险。将数据存储在 S3 中,可以利用其高达99.999999999%(11个9)的设计持久性和几乎无限的扩展能力。这意味着即使用户数据增长到TB甚至PB级别,存储层也能轻松应对,而无需对服务器进行任何改造。
- 计算资源的灵活性:当应用逻辑(EC2实例)与持久化数据(S3)解耦后,EC2实例本身就变成了一个可以随时替换的"无状态"或"半状态"组件。您可以根据负载需求轻松地更换实例类型(例如,从t3.micro升级到m5.large),或者在实例发生故障时快速启动一个新实例并重新挂载应用,而宝贵的用户数据始终安全地存放在S3中,不受影响。这种分离是实现高可用性和简化运维的关键一步,它将"关注点分离"这一软件工程原则成功地应用到了基础设施层面。
1.2 核心资源配置:启动并加固您的 EC2 实例
开始构建这个架构的计算核心。
- 启动EC2实例:
登录亚马逊云科技管理控制台,导航至EC2服务。
选择"启动实例",选择一个合适的亚马逊云机器映像(AMI),例如最新的Ubuntu Server长期支持版(LTS)。
选择一个实例类型。对于起步项目,通用型的t3.micro或t3.small是理想的选择,它们提供了良好的基准性能和突发能力。
- 配置网络与安全组:
在配置实例的步骤中,您需要将其放置在一个虚拟私有云(VPC)中。对于初学者,使用默认VPC即可。
安全组是实例级别的虚拟防火墙,至关重要。根据官方文档的指导,需要创建一个新的安全组并配置入站规则 。点击"添加规则",创建一个类型为"HTTP"的规则,端口范围为80,来源设置为 0.0.0.0/0和::/0。这允许来自任何IPv4和IPv6地址的公共Web流量访问NextCloud应用 。
为了安全管理,还应添加一条"SSH"规则,端口为22。但与HTTP规则不同,其来源应严格限制为您的个人或办公室的IP地址,而不是0.0.0.0/0,这能极大程度地降低被恶意扫描和暴力破解的风险。
- 分配并关联弹性****IP:
EC2实例在默认情况下,每次停止和启动后其公共IP地址都会改变。这对于一个需要稳定访问的服务是不可接受的。需要一个固定的IP地址。
在EC2控制台的左侧导航栏中,找到"网络与安全"下的"弹性IP"。
点击"分配弹性IP地址"来获取一个新的静态公网IP 。
分配成功后,选中这个IP地址,点击"操作"按钮,选择"关联弹性IP地址"。在关联页面中,选择刚刚创建的EC2实例,完成关联 。现在,这个固定的IP地址就成为了云盘的永久入口。
1.3 存储层构建:为无限扩展配置 S3 存储桶
接下来,创建用于存放所有用户文件的后端存储。
- 创建S3存储桶:
导航至S3服务控制台,点击"创建存储桶"。
输入一个全球唯一的存储桶名称,并选择一个离您或您的用户最近的区域,以降低延迟。
在"阻止公有访问权限"设置中,保持默认的"阻止所有公有访问权限"为开启状态。这是一个关键的安全设置。不希望任何人能够通过URL直接访问存储桶中的文件;所有的访问都将通过NextCloud应用以编程方式进行,并由IAM进行严格授权。
为了增强数据安全性,建议在"默认加密"选项中启用"服务器端加密",选择SSE-S3即可。这确保了所有上传到S3的文件都会被自动加密,增加了数据静态时的安全性。
1.4 安全集成:通过 IAM 授予应用程序访问权限
这是连接计算层和存储层的安全桥梁。将创建一个专门的IAM用户,并授予其访问S3的权限,供NextCloud应用使用。
这个过程体现了云安全的一个核心原则:为应用程序创建独立的、权限受限的身份,而不是使用具有过高权限的账户密钥。如果EC2实例或NextCloud应用本身被攻破,攻击者获得的权限将被限制在这个特定IAM用户的能力范围内,从而极大地缩小了安全事件的"爆炸半径"。
- 创建IAM用户:
导航至IAM服务控制台,在左侧选择"用户",然后点击"添加用户" 。
为用户输入一个描述性的名称,例如nextcloud-s3-user。
在"选择亚马逊云访问类型"中,仅勾选"编程访问"(或"访问密钥")。这会为该用户生成一个访问密钥ID和私有访问密钥,专门用于API、CLI等程序调用,而非控制台登录 。
- 附加权限策略:
在下一步中,选择"直接附加现有策略" 。
在策略筛选框中输入"s3",然后勾选AmazonS3FullAccess策略 。
专业实践提示:AmazonS3FullAccess策略授予了对账户中所有S3存储桶的完全控制权限。在真实的生产环境中,最佳实践是遵循"最小权限原则"。您应该创建一个自定义策略,明确地将权限限制在GetObject, PutObject, DeleteObject, ListBucket等操作,并且只针对刚刚创建的那个特定存储桶。但对于本教程,使用托管策略可以简化流程。
- 保存凭证:
继续点击下一步,直到用户创建成功。在最后的页面上,系统会显示该用户的"访问密钥ID"和"私有访问密钥" 。这是唯一一次能够看到完整私有访问密钥的机会,必须立即将其复制并保存在一个安全的地方(例如密码管理器中)。
切勿将这些密钥硬编码到代码中或提交到公共代码仓库。
1.5 部署与配置:将 NextCloud 连接到 S3 后端
万事俱备,现在进行最后的组装。
- 安装****NextCloud :
- 使用之前为安全组配置的密钥对和弹性IP地址,通过SSH客户端连接到您的EC2实例。
- 在实例上安装Web服务器(如Apache或Nginx)、PHP以及数据库(如MySQL或MariaDB),即所谓的LAMP或LEMP环境。
- 下载并部署NextCloud应用代码到Web服务器的根目录。
- 配置外部存储 :
- 通过浏览器访问您的弹性IP地址,您将看到NextCloud的安装向导。完成管理员账户和数据库的初始设置。
- 登录NextCloud后,导航至右上角的个人头像,点击"应用"。在"已禁用的应用"列表中找到"External storage support"并启用它 。
- 启用后,再次点击个人头像,进入"设置",在左侧的管理菜单中找到"外部存储" 。
- 连接****Amazon S3:
在"外部存储"页面,选择"添加存储",然后在下拉菜单中选择"Amazon S3" 。
填写配置信息:
- 文件夹名称:为这个S3挂载点起一个名字,例如MyS3Drive。
- 存储桶:输入您之前创建的S3存储桶的准确名称。
- 区域:选择存储桶所在的区域。
- 访问密钥:粘贴您在1.4节中保存的IAM用户的"访问密钥ID"。
- 私有密钥:粘贴对应的"私有访问密钥"。
- 点击确认。如果所有信息都正确,NextCloud旁边会出现一个绿色的对勾,表示连接成功。
现在,回到NextCloud的主界面,您会看到一个名为MyS3Drive的新文件夹。尝试上传一个文件到这个文件夹中。然后,切换到亚马逊云科技的S3控制台,浏览您的存储桶,您会惊喜地发现,刚刚上传的文件已经作为一个对象出现在了S3中。您已成功构建了一个计算与存储分离的、具备高持久性和高可扩展性的弹性单体应用。
2. 无服务器革命 ------ 使用亚马逊云科技 Lambda 与 API Gateway 开发动态 API
欢迎来到无服务器(Serverless)的世界。在这个范式中,彻底告别服务器管理------无需再关心操作系统补丁、Web服务器配置或容量规划。焦点将转移到编写响应事件的业务逻辑代码上。本教程将指导您使用Aamzon Lambda和Amazon API Gateway这两个核心服务,构建一个功能强大、可自动伸缩且成本效益极高的动态API。
2.1 无服务器请求的剖析
在深入实践之前,理解无服务器API的工作流程至关重要。其核心是一个由事件驱动的请求-响应模型:
- 客户端请求:一个用户或应用程序通过互联网向一个特定的URL发送HTTP请求(例如GET, POST, PUT)。
- API Gateway****接收:这个URL实际上是Amazon API Gateway提供的一个终端节点(Endpoint)。API Gateway作为API的"前门",负责接收所有传入的请求。它可以处理认证、授权、请求校验、速率限制等任务。
- 触发Lambda函数:API Gateway根据请求的路径和方法,将请求(包括其头部、查询参数、请求体等信息)打包成一个JSON格式的event对象,然后调用(触发)一个预先配置好的Amazon Lambda函数。
- Lambda函数执行:Amazon Lambda服务会动态地分配计算资源,在一个安全、隔离的环境中运行您的函数代码。您的代码从event对象中解析出所需的数据,执行业务逻辑------比如查询数据库、调用其他服务或进行计算。
- 返回响应:函数执行完毕后,将结果返回。
- API Gateway****响应客户端:API Gateway接收到Lambda函数的返回值,根据配置将其转换为标准的HTTP响应(包括状态码、头部和响应体),并最终发送回最初发起请求的客户端。
整个过程,开发者只需关注第4步中的函数代码。底层的计算资源分配、扩展(从零到每秒数千次请求)、高可用性以及运行环境维护,全部由亚马逊云科技自动处理。这种模式将开发者的认知负荷降至最低,使其能够专注于创造核心业务价值。
2.2 打造业务逻辑:您的第一个亚马逊云的 Lambda 函数
从编写API的核心------Lambda函数开始。
-
创建函数:
-
在亚马逊云科技管理控制台,导航至亚马逊云 Lambda服务。
-
点击"创建函数"。选择"从头开始创作"。
-
为函数命名,例如myDynamicGreeter。
-
在"运行时"下拉菜单中,选择您熟悉的编程语言,例如Python 3.x或Node.js 18.x。
- 在"权限"部分,Lambda会自动创建一个拥有基本执行权限的IAM角色。保持默认即可。
- 点击"创建函数"。
-
-
编写代码:
创建成功后,您会进入函数的代码编辑器。默认的代码模板展示了一个基本的处理程序结构。对于Python,它看起来像lambda_handler(event, context)。
event参数就是API Gateway传递过来的请求数据,context包含了运行时的信息。
从一个最简单的"Hello World"开始,让它返回一个静态的JSON响应。修改代码如下(以Python为例):
Python
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps({'message': 'Hello from Lambda!'})
}
点击"Deploy"按钮保存您的代码更改。
2.3 API 的前门:使用亚马逊云科技 API Gateway 创建 HTTP 终端节点
为这个Lambda函数创建一个公共的访问入口。
- 创建****API:
导航至亚马逊云 API Gateway服务控制台。
点击"创建API",在多种API类型中,为了简单起见,选择"HTTP API"并点击"构建"。
在"集成"步骤中,点击"添加集成"。
集成类型选择"Lambda",然后在下方的Lambda函数输入框中,选择刚刚创建的myDynamicGreeter函数。
为您的API命名,例如GreeterAPI。
- 配置路由:
在下一步"配置路由"中,需要定义哪个HTTP请求应该触发的Lambda函数。
方法选择"GET"。
资源路径输入/greeting。这意味着当一个GET请求访问.../greeting时,它将被路由到的Lambda集成。
将目标设置为刚刚创建的Lambda集成。
- 定义阶段与部署:
在"定义阶段"页面,阶段(Stage)是API的发布版本,例如dev、test或prod。这对于API的生命周期管理至关重要 。保留默认的$default阶段即可,它代表API会立即被部署。
检查配置无误后,点击"创建"。

API创建成功后,控制台会提供一个"调用URL"。将这个URL的末尾加上定义的路径/greeting
(例如https://xxxx.execute-api.us-east-1.amazonaws.com/greeting
),在浏览器中打开它。您应该能看到Lambda函数返回的JSON响应:{"message": "Hello from Lambda!"}
。

2.4 动态交互:在 Lambda 中处理客户端参数
静态API的用处有限,现在让它变得动态起来。目标是让API能够接收一个名为name的查询参数(例如/greeting?name=Alice),并返回个性化的问候。
- 修改Lambda函数以接收参数:
import json def lambda_handler(event, context): # 从查询字符串参数中获取'name',如果不存在则提供一个默认值 name = 'World' if 'queryStringParameters' in event and event and 'name' in event: name = event['name'] message = f"Hello, {name}!" return { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json' }, 'body': json.dumps({'message': message}) }
回到myDynamicGreeter函数的代码编辑器。
需要修改代码,使其从event对象中提取查询字符串参数。对于HTTP API,这些参数位于event中。
Python
import json
def lambda_handler(event, context):
# 从查询字符串参数中获取'name',如果不存在则提供一个默认值
name = 'World'
if 'queryStringParameters' in event and event and 'name' in event:
name = event['name']
message = f"Hello, {name}!"
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps({'message': message})
}
再次点击"Deploy"保存更改。
- 测试动态****API:
现在,回到浏览器,在之前的调用URL后面加上查询参数?name=Alice,然后访问。
您应该会看到响应变成了:{"message": "Hello, Alice!"}。
尝试更换name的值,或者不提供name参数,观察API是否按预期工作。
您已经成功地构建并部署了一个动态的、无服务器的API。这个过程揭示了API Gateway和Lambda之间一个至关重要的协作关系。API Gateway不仅仅是一个简单的请求转发器,它扮演了一个强大的中介和转换层角色。在更复杂的场景中(例如使用REST API类型时),您可以配置"集成请求"中的"映射模板" 。这允许您在将请求传递给Lambda之前,对其进行复杂的转换、重塑和验证。
这种设计模式创建了一个清晰的架构"接缝",将面向公众的API契约(HTTP请求的结构)与后端Lambda函数的内部实现细节(函数期望的event结构)解耦。这种解耦带来了巨大的好处:您可以独立地演进API(例如发布v2版本,改变参数名或结构),而只需修改API Gateway的映射配置,后端Lambda函数可能无需任何改动。它使得Lambda函数可以保持为一个干净、职责单一的组件,无需关心HTTP协议的复杂细节,这对于构建可维护、可演进的大型系统至关重要。
3. 边缘优势 ------ 托管高性能、安全的静态网站
在前两个部分,分别探讨了如何优化单体应用和构建动态后端。将目光转向现代Web应用的另一大支柱:前端。对于静态网站、单页应用(SPA)以及各种Web资源(图片、视频、CSS、JS文件),性能和安全性是用户体验的决定性因素。本教程将介绍一种业界标准的、性能卓越的架构模式:使用 S3进行存储,并结合亚马逊云 CloudFront进行全球内容分发和安全加速。
3.1 速度制胜的架构:S3、CloudFront 与全球边缘网络
目标是托管一个静态网站,但其架构远不止于将HTML文件上传到服务器。采用一种去中心化的交付模型:
- 源站 (Origin):网站文件(HTML, CSS, JavaScript, images等)将存储在Amazon S3存储桶中。S3作为源站,提供了高持久性和低成本的存储。
- 内容分发网络 (CDN):创建一个 亚马逊云 CloudFront分发。CloudFront是一个全球性的CDN,在全球数百个地理位置分散的"边缘站点"(Edge Location)拥有服务器。
- 交付流程:当用户尝试访问网站时,请求不会直接发送到位于某个特定区域的S3存储桶。相反,用户的DNS请求会被解析到离他/她地理位置最近的CloudFront边缘站点。
如果该边缘站点已经缓存了用户请求的文件,它会立即将文件返回给用户,实现极低的延迟。
如果文件未被缓存(即"缓存未命中"),边缘站点将向源站(S3存储桶)发起请求,获取文件,将其返回给用户的同时,也在本地缓存一份,以备后续请求使用。
这种架构的核心优势在于,它将内容从一个单一的、中心化的位置,推向了分布在全球各地的网络边缘。这带来的好处是多方面的:
- 极致性能:用户无论身在何处,都能从最近的节点获取内容,极大地降低了网络延迟(Latency),显著提升了网站加载速度。
- 增强的可扩展性与可用性:CloudFront的分布式特性可以轻松吸收巨大的流量洪峰(例如营销活动或突发新闻带来的访问量激增),而不会压垮源站。
- 提升的安全性:CloudFront本身就构成了一个强大的安全屏障。它可以帮助抵御常见的网络层和传输层DDoS攻击。此外,通过与亚马逊云 WAF(Web应用防火墙)等服务集成,还可以提供更高级别的应用层保护。
3.2 奠定基础:为静态网站托管配置 S3 存储桶
- 创建存储桶并上传文件:
在S3控制台创建一个新的存储桶。
准备一个简单的静态网站,至少包含一个index.html文件和一个error.html文件,以及一些CSS或JS文件。将这些文件上传到存储桶的根目录。
- 启用静态网站托管:
在存储桶的"属性"标签页中,找到"静态网站托管"功能,点击"编辑"。
选择"启用",并将索引文档设置为index.html,错误文档设置为error.html。
保存更改。此时,S3会提供一个网站终端节点URL。
- 配置存储桶策略(临时):
{ "Version": "2012-10-17", "Statement": }
为了让CloudFront能够访问这些文件,需要暂时允许公共读取。在"权限"标签页中,编辑"存储桶策略",并粘贴以下JSON策略(请将YourBucketName替换为您的存储桶名称):
Plain
{
"Version": "2012-10-17",
"Statement":
}
保存策略。请注意,这是一个临时步骤。在接下来的步骤中,将通过CloudFront的设置来强化安全,移除这个公共访问策略。
3.3 全球加速:设置亚马逊云 CloudFront 分发
这是本教程的核心环节,把S3源站接入全球网络。
- 创建分发:
导航至CloudFront服务控制台,点击"创建分发"。
在"源域"字段,从下拉列表中选择您刚刚创建的S3存储桶。CloudFront会自动填充正确的域名。
- 配置源访问(关键安全步骤):
在源设置中,找到"S3 存储桶访问"选项。选择"是,使用 OAC (源访问控制)"。源访问控制(OAC)是比传统的源访问身份(OAI)更新、更安全、功能更强大的推荐方式。
点击"创建控制设置",保留默认名称并创建。
CloudFront此时会显示一条信息,提示您需要更新S3存储桶策略。选择"复制策略",然后点击"转到S3存储桶权限"按钮。在S3控制台,用CloudFront提供的策略完全替换掉之前设置的临时公共访问策略。新的策略将只允许这个特定的CloudFront分发来访问您的S3对象,从而锁定了存储桶,实现了安全最佳实践。
- 配置查看器和缓存行为:
在"查看器协议策略"中,选择"Redirect HTTP to HTTPS"。这强制所有用户都通过安全的HTTPS连接访问您的网站。
在"缓存键和源请求"中,对于简单的静态网站,使用默认的CachingOptimized策略即可。
点击"创建分发"。分发的创建过程可能需要几分钟时间。
3.4 HTTPS 加固:使用亚马逊云 Certificate Manager (ACM) 配置 SSL/TLS 证书
一个现代化的、值得信赖的网站必须使用HTTPS。亚马逊云科技通过亚马逊云 Certificate Manager (ACM) 服务,让这个过程变得异常简单。
- 申请证书:
导航至ACM服务控制台。重要提示:必须在"美国东部(弗吉尼亚北部)"即 us-east-1区域申请证书,因为这是CloudFront要求的。
点击"请求证书",选择"请求公有证书"。
输入您的自定义域名,例如www.your-cool-project.com。您也可以使用通配符,如*.your-cool-project.com。
选择"DNS 验证"作为验证方法,这是推荐的方式。
- 完成域名验证:
创建请求后,ACM会为您提供一个CNAME记录。您需要登录到您的域名注册商(或如果您使用亚马逊云 Route 53,则在Route 53中)的DNS管理界面,将这个CNAME记录添加到您域名的DNS配置中。
ACM会自动检测此DNS记录。一旦检测成功,证书的状态就会变为"已颁发"。
- 关联证书到CloudFront:
回到您的CloudFront分发设置页面,点击"编辑"。
在"自定义SSL证书"字段,从下拉列表中选择您刚刚在ACM中颁发的证书。
在"备用域名 (CNAME)"字段中,添加您的自定义域名(www.your-cool-project.com)。
保存更改。
3.5 整合收官:DNS、部署与验证
最后一步,是将您的自定义域名指向CloudFront分发。
- 配置****DNS:
在您的DNS提供商的管理界面,为您的自定义域名(www.your-cool-project.com)创建一个新的记录。
记录类型应选择"CNAME"。
记录值应设置为您的CloudFront分发的域名(例如d1234abcd.cloudfront.net,您可以在CloudFront控制台找到它)。
如果您使用亚马逊云 Route 53作为DNS服务,推荐使用"A"记录并选择"别名(Alias)"选项,直接将流量路由到CloudFront分发,这比CNAME更优。
- 验证:
等待DNS记录在全球范围内传播生效(可能需要几分钟到几小时不等)。
在浏览器中输入您的自定义域名 https://www.your-cool-project.com。您应该能看到托管在S3上的网站,并且浏览器地址栏会显示安全的锁形图标。
要确认内容确实由CloudFront提供,可以打开浏览器的开发者工具,在"网络"标签页下查看响应头(Response Headers)。如果看到类似X-Cache: Hit from cloudfront或X-Cache: Miss from cloudfront的头部信息,就证明您的设置已成功,全球边缘网络正在为您服务。
以上就是本文的全部内容了,最后提醒一下,如果后续不再使用相关服务,别忘了在控制台关闭,避免超出免费额度产生费用~