设计地理分布式应用程序体系结构
- 8 分钟
当网络组件将请求路由到多个区域以缓解区域中断的影响时,我们必须设计能够响应主要区域和备用区域中这些请求的应用程序服务。
回想一下,先前我们计划用优先级后端分配来配置 Azure Front Door。 我们将美国东部区域指定为主要区域,并将美国西部区域指定为备用区域。 发生区域性故障时,请求会路由到非故障区域中的应用服务。 必须在每个区域中配置资源,以支持用户访问、复制存储和应用程序代码的故障转移。
在这里,我们将检查解决方案中的应用程序服务,并确定它们是否需要修改才能在多区域体系结构中运行。 具体而言,我们将介绍 Active Directory、静态内容存储、Web 应用、Web API、队列、Azure 函数和数据缓存。
Microsoft Entra 身份识别系统
在我们的发货跟踪门户中,用户可以通过输入跟踪号来跟踪其购买的交付。 但是,常规用户可以注册成员身份以访问高级功能,例如传递提示和其他统计信息。 我们开发了跟踪门户,用于将用户帐户存储在 Microsoft Entra ID 中。
默认情况下,Microsoft Entra ID 设计为全局系统。 因此,它并不容易受到区域故障的影响,我们不必修改系统的此组件。
Azure Blob 存储
静态内容(如图像和视频)以二进制大型对象(Blob)的形式存储在 Azure 存储帐户中,并通过 Azure CDN 向用户提供服务。
在我们的原始设计中,存储帐户包含在单个区域中,因为我们选择使用本地冗余存储(LRS)。 数据仅在具有 LRS 的单个数据中心内复制。 因此,如果此配置发生区域性中断,则存储帐户不可用。 CDN 缓存的任何静态内容仍可供用户使用。
区域冗余存储(ZRS)也是如此。 即使数据复制到此配置中的不同数据中心,所有这些数据中心仍位于同一区域。 区域性中断还会影响此配置中的存储帐户。
在我们的设计中,我们严重依赖 CDN 配置来缓存静态内容。 在服务中断期间,用户可能会请求尚未在 CDN 缓存中的静态文件。 此请求将导致无法显示的图形或视频。
选择异地冗余存储选项时,我们可以通过将存储帐户复制到多个区域来消除这种可能性。 只读复制选项也可用于防止在区域性中断期间添加静态内容。
我们需要在需要启用异地冗余时选择两个选项。 这些选项是读取访问异地冗余存储 (RA-GRS) 和读取访问异地区域冗余存储 (RA-GZRS)。 我们做出的选择取决于我们的预算和所需的正常运行时间百分比。
Azure 应用服务和 Azure 函数应用
我们的发货跟踪门户实现了两个 Azure 应用服务。 第一个应用服务托管实现面向用户的 Web 界面的 Web 应用,第二个应用托管移动应用用于跟踪发货数据的 Web API。 所有后台任务都作为 Azure 函数应用运行。
在我们的原始设计中,每个 Azure 应用服务都本地化为单个 Azure 区域。 我们将在次要区域(美国西部)创建第二个应用服务,并在其中部署 Web 项目以支持新的多区域体系结构。 我们将 Azure Front Door 优先级路由模式配置为在主要区域不可用时将请求发送到次要区域。
为了确保故障转移尽可能顺利,请确保 Web 应用程序不会将任何会话状态信息存储在内存中。 我们更改了网站,以确保最终不会丢失数据。 例如,如果代码将用户的发货列表存储在内存中,则发生故障转移时,此列表将丢失。
在未存储会话状态时,将处理每个 Web 请求,而不会影响另一个请求。 如果在用户会话过程中发生故障转移,则用户应不会察觉到故障转移。
我们对 Azure Function 应用做了类似的更改。 我们将在次要区域中创建 Azure 函数的单独实例,并将相同的自定义代码部署到主要区域中运行。
重要
将更新部署到应用服务或 Function App 服务中的自定义代码时,请记住将其分发到应用服务的所有实例。 如果想要自动执行此过程,Azure DevOps 具有可提供帮助的工具。
Azure 存储队列
在我们的原始单区域体系结构中,我们使用 Azure 存储帐户中的队列来管理应用服务和函数应用之间的通信。 当 Web 应用或 Web API 需要运行后台任务时,它会在队列中放置包含所有必需信息的消息。 函数应用监控队列以等待新消息,并通过在数据存储上运行必要的查询来执行后台任务。
当我们以这种方式使用队列时,我们可以有序地管理 Web 请求中的高需求。 当有多个后台任务要运行时,队列可能加长,但任务不会被删除。 它们会一直处于队列中,直到得到处理。 函数应用程序处理队列,并在需求下降时缩小队列的大小。 如果需求仍然存在,我们将增加函数应用的实例数。
对于发货跟踪门户的多区域版本,我们必须确保在系统故障转移时不会丢失队列项。 队列在 Azure 存储中定义,可以使用冗余选项进行异地复制。
请记住,由于队列支持读写操作,因此无法使用读取访问冗余选项。 应用服务必须将项添加到队列,并且函数应用必须从队列中删除已完成的项。 请改用异地冗余存储 (GRS) 或地理区域冗余存储 (GZRS)。
Azure Redis 缓存
我们使用 Azure Redis 缓存来最大程度地提高数据存储的性能。 Redis 会缓存从应用生成的所有查询结果,因为它们从数据库请求数据。 针对类似数据的任何进一步查询都不需要数据库查询,并从 Redis 缓存中提取。
对于多区域体系结构,我们在主区域和备用区域中创建 Redis 缓存实例。 请记住,发生故障转移时,备用区域中的 Redis 缓存很可能为空。 当数据填充新缓存时,该空缓存不会导致任何错误,但性能可能会暂时下降。