44、现代Web架构与应用实践:API网站、无服务器及容器技术

现代Web架构核心技术解析

现代Web架构与应用实践:API网站、无服务器及容器技术

1. API网站与搜索引擎索引问题

典型的API网站在浏览器中显示内容之前,需要从API获取内容。这就导致搜索引擎爬虫在索引API网站时,看到的只是大量代码,而没有实际内容。虽然可以将静态内容页面与API页面结合,但这又会回到静态页面内容管理困难的问题上。

近年来,搜索引擎在索引API驱动的网站方面取得了一些进展,部分爬虫能够看到检索到的内容。然而,其效果仍不如索引静态网站,并且可能会因额外的延迟或复杂的代码结构而受到惩罚。

2. 交互式网站页面的解决方案

交互式网站页面,如联系表单,可以将静态生成的HTML与公共API结合,用于提交和检索信息。对于特定用户的独特内容页面,可设置登录限制并由API驱动,因为这类页面通常不需要进行SEO优化。

3. 无服务器内容管理系统(CMS)架构的优势

这种架构结合了不同方法的优点,同时避免了相关挑战:
- 非技术型网站所有者可以通过用户友好的CMS界面管理网站内容。
- 搜索引擎将该网站视为静态网站,所有内容都已嵌入,便于索引。
- 必要时可通过公共API支持交互功能,页面可以是静态的,少量动态部分不会影响SEO。
- 网站速度极快,通过最近的CDN端点快速交付,避免了与后端或数据库通信通常带来的延迟。

4. 无服务器网站的实用技巧
  • 页面渲染引擎 :仔细考虑如何从数据和HTML模板渲染输出页面。可以使用现有的库,如EJS(https://ejs.co/),也可以开发自定义库。要考虑未来的潜在需求,因为更改渲染引擎可能需要大量工作。
  • 模板更新 :考虑提供为给定模板以及整个公共网站重新生成所有页面的选项,这在模板更改时非常有用。
  • CDN缓存失效 :发布新网站文件后,务必使CDN缓存失效,否则内容管理员将看不到更新。
  • 文件分离 :将生成的页面与网站模板使用的静态内容(如JavaScript、CSS和图像文件)分开存储。可以使用单独的存储桶,这样更便于清理或重新生成所有HTML页面。
  • 微服务选择 :页面构建器微服务可以是单个微服务来处理所有模板,也可以为每个模板创建一个独特的微服务。实践中发现,大多数发布步骤对于不同模板是相同的,因此使用单个微服务更合理。该微服务会为DynamoDB触发的每个作业或发布请求并行运行。
  • 数据配置文件 :在HTML模板中包含一个config.json文件,其中包含每个模板应从数据库加载哪些数据的信息,这将提高渲染引擎中数据检索的效率。
  • 数据库使用 :对于内容存储,使用单个DynamoDB,通过分区键分离不同语言和类型,使用范围键唯一标识给定页面。对于电子商务,可以添加额外的DynamoDB用于产品库存和订单管理,QLDB可用于交易记录。需要注意的是,由于公共网站是静态的,只有网站管理员会与内容数据库交互。
5. 虚拟主机的创建

创建虚拟主机是一个有趣且具有教育意义的案例。使用Amazon Sumerian(一种基于浏览器的无服务器3D引擎服务)创建一个带有3D化身(虚拟主机)的3D环境,然后通过语音和一些反应行为使主机具有交互性。

  • 语音合成与输入 :Polly可以实现文本到语音的转换,并与Sumerian中的化身很好地集成,使化身看起来能够说话。对于用户输入,可以使用Chrome浏览器的语音识别功能或触摸输入。在大型竖屏触摸屏电视上,这种体验效果极佳,使化身几乎栩栩如生。
  • 用户跟踪 :在浏览器中,可以使用JavaScript实现的凝视跟踪功能,通过摄像头捕捉用户的视频并跟踪其移动。不过,这种功能可能会让人感觉有些怪异。可以参考的跟踪库:https://webgazer.cs.brown.edu/。
  • 实现步骤
    • 首先,Sumerian需要一个Cognito用户池,其中配置了具有适当Polly权限的授权和未授权角色,以便访问Polly并将其作为化身的语音服务。然后在Sumerian的AWS配置中配置Cognito用户池ID,该配置可在右侧的设置面板中找到。
    • 设计一个3D场景作为背景,并从库中选择一个可用的化身。Sumerian提供了多种不同性别和种族的化身,但大多数具有类似的卡通风格。目前,它不提供作为服务一部分的自定义化身,但可为某些品牌提供定制(且成本较高)服务。
    • Polly在Sumerian中的集成非常无缝且易于配置。可以在文本框中选择语音并输入化身应说的文本,也可以通过脚本实现。如果要实现完整的聊天机器人体验,Lex的集成也相对简单。
    • 最终发布的Sumerian场景可以通过公共URL访问,适用于早期原型开发,也可以进行安全设置并嵌入到Web应用程序中。Amplify提供了专门用于Sumerian场景的库,可使嵌入过程更加容易。
    • 可以使用JavaScript在Sumerian中包含API连接、凝视跟踪等功能,也可以在Web应用程序中实现这些功能,并在Sumerian中创建与Web应用程序通信的函数。Sumerian提供了各种事件的钩子和通知,有助于简化这一过程。
    • 网络摄像头和Rekognition可以用于从Web应用程序的用户资料中识别用户。一旦识别成功,化身可以提供个性化的欢迎消息。此外,Rekognition还可用于在交互过程中监测用户的表情,以确定他们对某些活动或主题的情绪。
    • Lex服务具有出色的语音识别能力,可引导用户完成特定的订单流程。但对于非订单流程的用例,它的灵活性较差。Chrome浏览器具有类似强大的语音识别功能,且不受特定流程或用例的限制。使用Chrome选项意味着需要围绕识别的文本开发逻辑,但它为实现特定应用程序的需求提供了更大的灵活性,并且与Lex相比,延迟要低得多。目前大多数其他浏览器不具备类似功能,因此如果化身通过互联网公开访问,需要确保用户使用Chrome浏览器。
    • 在教育场景中,可以加入物联网灯泡,让用户可以要求化身打开或关闭灯光,这些物理元素可以极大地增强学习体验。
6. 真正的无服务器容器 - Fargate

2017年,AWS推出了Fargate,这是一种完全托管的容器服务。云提供商负责管理底层服务器集群、操作系统和平台软件。用户创建并将Docker容器部署到其中,只需为容器运行时分配的资源付费,而不考虑利用率。Fargate支持长时间运行和按需任务容器。

任务容器的延迟比Lambda微服务高,因此更倾向于使用Lambda作为无服务器后端。然而,Lambda存在一些限制,例如15分钟的时间限制,在处理视频时可能会成为问题。

Fargate的计费模式不是严格意义上的无服务器,因为它按运行时间计费,而不是按执行时间计费,这包括了未充分利用和可计费的空闲时间。不过,就像实时视频案例研究一样,可以使用Lambda按需创建Fargate容器,以尽量减少需要付费的空闲时间。

7. 使容器真正无服务器的方法

使用CDK编写所有固定基础设施,并使用Lambda微服务加载所需的按需服务。为了使容器真正实现无服务器,只应支付存储、请求和容器执行作业所花费的时间费用。为避免给容器提供对S3存储桶的完全访问权限,将在Lambda中生成签名的GET和POST S3 URL,并通过SQS消息将这些URL传递给容器。

容器将从签名的GET URL检索视频文件,并将结果存储在签名的POST URL上。作业完成后,容器将通过另一条SQS消息报告,触发一个Lambda函数来确认作业并终止容器。使用SQS队列方法可以使Lambda微服务与VPC中的容器完全解耦。

8. 容器启动和运行的步骤及相关费用
步骤 描述 费用(新加坡地区)
1. 创建、配置和构建Docker容器 可参考本地构建和测试Docker容器的指南。示例中使用了修改后的容器(https://hub.docker.com/r/jrottenberg/ffmpeg/),并添加了bash脚本来处理与SQS的交互和执行视频作业。 $0(可本地完成)
2. 将容器放入注册表 使用AWS的Elastic Container Registry(ECR)服务,将容器配置和文件放入CDK堆栈的/src文件夹中,并使用ecrassets.DockerImageAsset()将容器构建并部署到ECR。 $0.10/GB/月存储和$0.12/GB数据传输(总费用取决于容器大小,每次启动容器会产生数据传输费用)
3. 在ECS中启用长ARN名称 如果要使用资源标签,必须启用长ARN名称。可通过AWS CLI的三个命令实现:
bash<br>aws ecs put-account-setting-default --name serviceLongArnFormat --value enabled<br>aws ecs put-account-setting-default --name taskLongArnFormat --value enabled<br>aws ecs put-account-setting-default --name containerInstanceLongArnFormat --value enabled<br>
如果工作站有多个AWS配置文件,记得在命令中添加 --profile [配置文件名称]
$0
4. 创建支持服务 为该用例创建两个SQS队列,一个用于容器执行的新作业,另一个用于容器报告完成的作业。
typescript<br>const sqsNew = new sqs.Queue(this, "ffmpegJobNew", {<br> visibilityTimeout: cdk.Duration.seconds(7200)<br>});<br>const sqsDone = new sqs.Queue(this, "ffmpegJobDone", {<br> visibilityTimeout: cdk.Duration.seconds(300)<br>});<br>
$0.0000004/消息
5. 创建策略和角色 使用CDK创建必要的策略并将其附加到角色上。需要两个角色:一个执行角色用于从CDK管理的ECR存储库加载容器,一个任务角色用于容器访问资源。
typescript<br>const policyExecution = new iam.PolicyStatement({<br> effect: iam.Effect.ALLOW,<br> resources: [ffmpegContainer.repository.repositoryArn],<br> actions: [<br> "ecr:BatchCheckLayerAvailability",<br> "ecr:GetDownloadUrlForLayer",<br> "ecr:BatchGetImage"<br> ]<br>});<br>const erole = new iam.Role(this, "roleEcsExecution", {<br> assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com")<br>});<br>erole.addToPolicy(policyExecution);<br>const policyNew = new iam.PolicyStatement({<br> effect: iam.Effect.ALLOW,<br> resources: [sqsNew.queueArn],<br> actions: [<br> "sqs:GetQueueAttributes",<br> "sqs:ReceiveMessage",<br> "sqs:DeleteMessage"<br> ]<br>});<br>const policyDone = new iam.PolicyStatement({<br> effect: iam.Effect.ALLOW,<br> resources: [sqsDone.queueArn],<br> actions: ["sqs:SendMessage"]<br>});<br>const role = new iam.Role(this, "roleEcsTask", {<br> assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com")<br>});<br>role.addToPolicy(policyNew);<br>role.addToPolicy(policyDone);<br>
$0
6. 创建任务定义 使用CDK创建ECS任务定义,定义容器分配的资源(CPU和内存)。
typescript<br>const ecstask = new ecs.FargateTaskDefinition(this, "ecstask", {<br> cpu: 1024, // 1 cpu<br> memoryLimitMiB: 2048, // 2gb memory<br> executionRole: erole,<br> taskRole: role<br>});<br>
$0
7. 将容器添加到任务定义 使用CDK的addContainer函数将特定容器添加到任务定义中。
typescript<br>let imageTag = ffmpegContainer.imageUri.split(':').pop();<br>ecstask.addContainer("ffmpeg", {<br> image: ecs.ContainerImage.fromEcrRepository(<br> ffmpegContainer.repository,<br> imageTag<br> ),<br> environment: {<br> INPUT_QUEUE_URL: sqsNew.queueUrl,<br> OUTPUT_QUEUE_URL: sqsDone.queueUrl<br> },<br> workingDirectory: "/app"<br>});<br>
如果需要从外部访问容器服务,可在此处添加端口映射。
typescript<br>.addPortMappings({<br> containerPort: 1234,<br> protocol: ecs.Protocol.TCP<br>});<br>
$0
8. 创建任务运行的集群(和VPC) 有三种方式创建集群和VPC:
- 使用现有VPC :如果已有具有公共子网或带有NAT的私有子网的VPC,可以使用它。在CDK中创建ECS集群并引用现有VPC。
typescript<br>const myCluster = new ecs.Cluster(this, "ecscluster", {<br> clusterName: "myCluster",<br> vpc: <EXISTING_VPC><br>});<br>
费用:$0(在已有VPC费用基础上无额外费用)
- 使用公共子网 :创建一个带有公共子网和互联网网关的VPC,不包含可计费的NAT网关。通过安全组和映射端口控制对容器的访问。
typescript<br>const myVPC = new stack.services.ec2.Vpc(this, "myvpc", {<br> cidr: "10.0.0.0/16",<br> natGateways: 0,<br> subnetConfiguration: [{<br> cidrMask: 24,<br> name: "mySubnet1",<br> subnetType: ec2.SubnetType.PUBLIC<br> }]<br>});<br>const myCluster = new ecs.Cluster(this, "ecscluster", {<br> clusterName: "myCluster",<br> vpc: myVPC<br>});<br>
费用:$0(如果配置正确,无计费组件)
- 在Lambda中动态创建VPC和集群 :这是最复杂的选项,启动任务有大约一分钟的延迟,因为启动NAT需要一些时间。每分钟运行任务的成本也比其他选项高。主要适用于企业中要求使用私有子网部署容器的情况。需要确保有监控措施,避免出现孤立的VPC导致闲置费用增加。
费用:$0.059/小时或部分小时(每个NAT运行费用,一个NAT通常足够)
9. 启动容器 完成上述步骤后,即可启动容器。 -
9. 相关注意事项
  • 安全组 :建议为容器创建专门的安全组,以便控制访问。如果容器需要外部访问,且在创建任务定义时配置了端口映射,则需要在安全组中添加所需的端口。如果选择在Lambda中动态创建VPC和集群,则需要在Lambda中创建安全组。
const secGroup = new ec2.SecurityGroup(this, "secgroup", {
  vpc: myVPC,
  allowAllOutbound: false
});
secGroup.addIngressRule(
  ec2.Peer.ipv4("0.0.0.0/0"),
  ec2.Port.tcp(1234),
  "Example of opening an ingress port for the container"
);
secGroup.addEgressRule(
  ec2.Peer.ipv4("0.0.0.0/0"),
  ec2.Port.tcp(443),
  "Example of opening an egress port for the container"
);
  • VPC网关 :如果与S3和/或DynamoDB一起工作,可以使用VPC端点网关免费连接VPC与这些服务,避免通过公共互联网传输数据。该免费选项仅支持这两个服务。另一种选择是使用PrivateLink,它有每小时费用,只有在从Lambda为任务持续时间添加PrivateLink时,才被视为无服务器。如果使用私有子网,为避免使用公共互联网进行容器镜像加载和访问CloudWatch,可以启用PrivateLink。如果要避免使用NAT,则必须使用PrivateLink使Fargate正常工作。
  • CloudWatch日志 :可以在Fargate容器上启用控制台输出到CloudWatch日志,方便调试、主动监控以及成本或活动跟踪。
const logGroup = new logs.LogGroup(this, "ecslogs-abc", {
  logGroupName: "/aws/ecs/groupname",
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  retention: logs.RetentionDays.THREE_DAYS
});
ecstask.addContainer("ffmpeg", {
  // ...
  logging: new ecs.AwsLogDriver({
    streamPrefix: "MYSTREAM",
    logGroup: logGroup,
    retention: logs.RetentionDays.THREE_DAYS
  })
});

同时,执行任务角色需要以下权限和资源:

"logs:CreateLogStream",
"logs:PutLogEvents"
"arn:aws:logs:" + region + ":" + account + ":log-group:/aws/ecs/groupname/*"

综上所述,通过合理运用无服务器架构、API技术以及容器服务,可以构建出高效、灵活且易于管理的现代Web应用程序。在实际应用中,需要根据具体需求和场景选择合适的技术和配置,以达到最佳的性能和成本效益。

现代Web架构与应用实践:API网站、无服务器及容器技术

10. 无服务器CMS架构流程总结

为了更清晰地理解无服务器CMS架构的实现过程,下面是一个简要的mermaid流程图:

graph LR
    A[创建内容] --> B[CMS管理内容]
    B --> C[数据存储到DynamoDB]
    C --> D[模板渲染生成页面]
    D --> E[页面存储到CDN]
    E --> F[搜索引擎索引]
    G[用户请求] --> E
    E --> H[返回页面给用户]

该流程图展示了无服务器CMS架构中内容从创建到最终呈现给用户的整个过程。首先,网站所有者在CMS中创建和管理内容,这些内容被存储到DynamoDB中。然后,使用模板渲染引擎根据数据和HTML模板生成页面,并将页面存储到CDN上。搜索引擎可以对CDN上的页面进行索引,当用户发起请求时,CDN直接返回页面给用户。

11. 虚拟主机交互流程分析

虚拟主机的交互流程可以用以下mermaid流程图表示:

graph LR
    A[用户输入] --> B{输入类型}
    B -->|语音| C[Chrome语音识别]
    B -->|触摸| D[触摸输入处理]
    C --> E[处理识别文本]
    D --> E
    E --> F[与Lex或自定义逻辑交互]
    F --> G[生成回复文本]
    G --> H[Polly语音合成]
    H --> I[化身语音输出]
    J[摄像头捕捉] --> K[凝视跟踪或Rekognition识别]
    K --> L[个性化交互或情绪监测]
    L --> F

用户可以通过语音或触摸进行输入。语音输入通过Chrome的语音识别功能进行处理,触摸输入则直接进行处理。处理后的文本与Lex或自定义逻辑进行交互,生成回复文本。回复文本经过Polly语音合成后,由化身进行语音输出。同时,摄像头可以捕捉用户的视频,进行凝视跟踪或使用Rekognition进行用户识别和情绪监测,这些信息也会反馈到交互逻辑中,实现个性化的交互体验。

12. Fargate容器部署流程优化

在使用Fargate部署容器时,为了提高效率和降低成本,可以对部署流程进行优化。以下是优化后的步骤列表:
1. 提前规划 :在开始部署之前,明确容器的资源需求、网络配置和安全要求。考虑使用现有VPC或公共子网,避免不必要的NAT网关费用。
2. 自动化构建 :使用CDK自动化构建容器和相关资源,如任务定义、角色和策略。这样可以减少手动配置的错误和时间成本。
3. 按需创建 :使用Lambda按需创建Fargate容器,避免长时间的空闲费用。在任务完成后,及时终止容器。
4. 监控和调整 :设置监控和报警机制,实时监测容器的运行状态和资源使用情况。根据实际情况调整容器的资源分配,以提高效率和降低成本。
5. 安全配置 :为容器创建专门的安全组,严格控制访问权限。使用VPC端点网关或PrivateLink确保数据传输的安全性。

13. 不同技术的对比与选择
技术 优点 缺点 适用场景
API网站 数据实时更新,可动态展示内容 搜索引擎索引困难,可能有延迟和复杂代码结构问题 需要实时数据展示的网站,如新闻、金融类网站
静态网站 搜索引擎友好,加载速度快 内容更新困难,管理成本高 内容相对固定的网站,如企业官网、博客
无服务器CMS架构 易于管理,搜索引擎友好,速度快 需要一定的技术基础进行配置 非技术型网站所有者管理的网站,需要SEO优化的网站
Fargate容器 完全托管,无需管理底层服务器 计费模式可能存在空闲费用,任务容器延迟较高 需要运行长时间任务或对资源需求较大的应用,如视频处理、大数据分析
Lambda微服务 响应速度快,按执行时间计费 有时间和资源限制 轻量级、短时间运行的任务,如数据处理、事件触发

在选择技术时,需要根据项目的具体需求、预算和团队技术能力进行综合考虑。例如,如果项目对搜索引擎优化要求较高,且内容更新不频繁,可以选择静态网站或无服务器CMS架构;如果需要处理大量数据或长时间运行的任务,Fargate容器可能是更好的选择;而对于轻量级的任务,Lambda微服务则可以提供高效的解决方案。

14. 总结与展望

通过对API网站、无服务器CMS架构、虚拟主机和Fargate容器等技术的介绍和分析,我们可以看到现代Web架构提供了丰富的选择,能够满足不同类型网站和应用的需求。这些技术的结合使用,可以构建出高效、灵活、安全且易于管理的Web应用程序。

在未来,随着技术的不断发展,无服务器架构和容器技术可能会更加成熟和普及。例如,无服务器技术可能会进一步降低成本和提高性能,容器编排工具可能会更加智能化和自动化。同时,随着人工智能和机器学习的发展,虚拟主机的交互能力可能会得到进一步提升,为用户提供更加个性化和自然的交互体验。

在实际应用中,我们需要不断关注技术的发展趋势,结合项目的实际需求,选择最合适的技术和架构。同时,要注重安全和性能的优化,确保Web应用程序的稳定运行和用户体验。通过不断学习和实践,我们可以更好地掌握这些技术,为现代Web应用的发展做出贡献。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值