三层架构图:表示层、应用层与数据层

结合 AWS 示例讲解三层架构图:表示层、应用层和数据层、子网、安全组、扩展方式以及常见错误。

· 创始人兼开发者

发布于

三层架构图:表示层、应用层与数据层

三层架构是如今大多数 Web 应用在底层仍然采用的形态:一部分负责提供用户界面,一部分负责运行业务逻辑,还有一部分负责存储数据。它很老、很无聊,却是大多数系统正确的起点,因为每一层都可以独立扩展、独立加固。

本文讲解这三层,展示它们如何借助子网和安全组映射到云网络中,并画出一个跨两个可用区的典型 AWS 部署。同样的结构适用于任何云平台。

三个层

层 职责 典型组件 扩展方式
表示层 交付界面并接收请求 CDN、静态资源、负载均衡器、Web 服务器 边缘缓存、增加实例
应用层 业务逻辑和 API 应用服务器、容器、函数 增加实例、自动扩缩容
数据层 存储和读取状态 关系型数据库、缓存、对象存储 更大的实例、副本、缓存

让它成为一种架构、而不只是三个方框的规则是:每一层只和相邻的层通信。浏览器永远不会直接访问数据库,表示层也永远不会执行 SQL。

AWS 在其 三层架构概述 中描述了这种模式,其中也包括用函数替代应用服务器的无服务器变体。

把各层映射到网络

当各层位于路由不同的子网中时,它们才成为真正的边界:

  • 公有子网 只放必须能从互联网访问的东西:负载均衡器和 NAT 网关。
  • 私有应用子网 放应用服务器。它们可以通过 NAT 出站访问互联网,用于更新和调用 API,但除了经过负载均衡器之外,外部没有任何途径能访问它们。
  • 私有数据子网 放数据库和缓存,完全没有到互联网的路由。

接着用 安全组 只放行相邻层的流量:数据库的 5432 端口只接受来自应用层安全组的访问,而不是某个 IP 段。引用安全组而不是地址,能让规则在实例增减时依然正确。

跨可用区的高可用

让每一层至少运行在两个可用区中:

  • 负载均衡器在设计上就是跨可用区的。
  • 应用服务器运行在一个自动扩缩容组中,每个可用区都有实例。某个可用区出故障时,其他可用区接管流量,扩缩容组会补足容量。
  • 数据库在另一个可用区配有同步的备用实例。使用 Amazon RDS Multi-AZ 时,切换到备用实例是自动的,端点名称也保持不变。

让应用层保持无状态,这样任何实例都能处理任何请求:会话放进共享缓存或数据库,上传文件放进对象存储,实例磁盘上不保存任何重要的东西。可以在工作时间随机终止一台应用服务器来检验;如果用户有所察觉,就说明还有状态藏在实例上。

分别扩展每一层

各层的扩展方式不同,这正是要把它们分开的原因:

  • 表示层: CDN 吸收大部分静态流量,吸收多少由缓存头决定。
  • 应用层: 增加实例。按请求数或 CPU 扩缩容,并让实例快速启动。
  • 数据层: 最难的一层。先纵向扩展,读多写少时加只读副本,为热点键加缓存,把分片当作最后的手段。

一个请求穿过各层的过程

跟随一位正在加载订单历史的用户:

  1. DNS 返回 CDN 的地址。浏览器请求页面,HTML、脚本和图片来自 CDN 的缓存或其后的静态存储桶。
  2. 页面调用 GET /api/orders。CDN 把动态路径转发给负载均衡器,负载均衡器终止 TLS,并在任一可用区中选择一台健康的应用服务器。
  3. 应用服务器从缓存中读取会话,确认用户已登录,然后向主数据库查询订单。
  4. 响应经由负载均衡器和 CDN 返回;由于响应是私有的,CDN 不会缓存它。

每一跳只跨越一个层边界,每个边界都恰好只有一个允许的入口。这让整个设计易于理解,也易于加固。

成本与合理规格

数据层通常占账单的大头,事后也最难缩减,所以要根据实测而不是猜测来确定它的规格。应用层最容易调整:从小规格开始,按真实负载扩展,让自动扩缩容来应对峰值。NAT 网关和跨可用区流量是最容易让人意外的开销项;尽量把通信频繁的流量留在同一个可用区内,并为对象存储使用 VPC 端点,免得应用服务器每次上传都要付 NAT 费用。

架构图

用户访问 CDN,CDN 从存储桶提供静态文件,并把动态请求转发给公有子网中的负载均衡器。负载均衡器把流量发送到私有子网中可用区 A 和 B 的应用服务器,应用服务器使用一个在可用区 B 有备用实例的主数据库,以及一个会话缓存。

15 个组件 · 10 个连接

在 Archboard 中打开
图表内容
  • Users
  • DNS
  • CDN
  • Static assets bucket
  • VPC across two availability zones
  • Presentation tier: public subnets
  • Application load balancer
  • Application tier: private subnets
  • App servers, zone A
  • App servers, zone B
  • Data tier: private subnets, no internet route
  • Database primary, zone A
  • Standby, zone B
  • Session cache
  • HTTPS
  • resolve
  • static files
  • dynamic requests
  • SQL
  • sync
  • sessions
部署在 AWS 上的三层 Web 应用。CDN 提供静态文件,并把动态请求转发给公有子网中的负载均衡器;两个可用区的应用服务器运行在私有子网中,数据库和会话缓存位于没有互联网路由的数据层。

这张图的读法如下:

  • 顶部: 用户解析 DNS 并连接到 CDN,CDN 从存储桶提供静态文件,并转发动态请求。
  • 表示层: 应用负载均衡器是公有子网中唯一的组件。
  • 应用层: 可用区 A 和 B 的应用服务器位于私有子网中,只接收来自负载均衡器的流量。
  • 数据层: 可用区 A 的主数据库同步复制到可用区 B 的备用实例;应用服务器还使用一个会话缓存。这一层没有到互联网的路由。
  • Markdown 块 列出了安全组规则,真正落实分层的正是这些规则。

常见错误

  • 把数据库放在公有子网里, 说是“临时的”,只为了从笔记本上快速查个数。应改用堡垒机或托管的会话工具。
  • 层与层之间放行整个 CIDR 段的安全组, 而不是引用相邻层的安全组。
  • 应用服务器上保存状态: 会话放在内存里,上传文件存在本地磁盘。自动扩缩容和故障切换时就会丢数据。
  • 为了省钱让数据库只用一个可用区, 而应用层却分布在三个可用区。
  • 跳过 CDN, 让每张图片都从应用服务器提供。
  • 应用服务器没有健康检查路径, 导致负载均衡器继续把流量发给连不上数据库的实例。

三层不够用的时候

三层描述的是一个应用。当系统发展成多个服务时,每个服务往往仍保持自己的三层结构,架构图则要上升一个层次,展示服务之间如何通信。微服务架构图 介绍了这一步。网络细节请参阅 AWS VPC 图,多区域部署请参阅 AWS 多区域架构图。

在 Archboard 中构建

  1. 使用 Google 或 GitHub 登录,并新建一张图。
  2. 添加 C4 模型节点包中的一个 人员、网络节点包中的一个 DNS,以及云节点包中的一个 CDN 和一个 对象存储 节点。
  3. 添加网络节点包中的一个 VPC,并在其中放入三个基础节点包中的 框架 节点,每层一个。
  4. 在表示层添加一个 云负载均衡器,在应用层添加两个 计算实例 节点,在数据层添加两个 托管数据库 节点以及数据节点包中的 Redis。
  5. 让每一层只连接相邻的层,并添加一个基础节点包中的 Markdown 块,写明安全组规则。如果你的环境已经用 Terraform 描述,Terraform 转架构图工具 可以为你生成第一版草图。

这个示例共用 15 个图表节点,在 Free 套餐的限制之内。

常见问题

三层架构中的三层分别是什么? 表示层(用户界面和入口)、应用层(业务逻辑和 API)以及数据层(数据库、缓存和存储)。

三层架构过时了吗? 没有。它是 Web 应用的默认形态。微服务和无服务器系统仍然包含同样的三种职责,而且往往是每个服务各有一套。

三层(tier)架构和三层(layer)架构有什么区别? layer 是代码内部的逻辑划分;tier 则是物理划分,分布在彼此独立、之间隔着网络边界的机器或服务上。

数据库应该放在公有子网里吗? 不应该。把它放在没有互联网路由的私有子网中,只允许应用层的安全组访问。

如何让三层应用实现高可用? 让每一层至少运行在两个可用区中,保持应用服务器无状态,并使用在另一个可用区有自动备用实例的数据库。

免费开始 — 1 个席位,无需信用卡。

相关文章

← 返回博客

一分钟打开画布

使用 Google 或 GitHub 登录。单席位免费,团队加入后再升级。