前端客户端通信

提示

此内容摘自电子书《为 Azure 构建云原生 .NET 应用程序》,可在 .NET 文档上获取,也可作为免费可下载的 PDF 脱机阅读。

Cloud Native .NET apps for Azure eBook cover thumbnail.

在云原生系统中,前端客户端(移动、Web 和桌面应用程序)需要一条信道,用于与独立的后端微服务进行交互。

有哪些选项?

为了简化操作,前端客户端可直接与后端微服务通信,如图 4-2 所示。

Direct client to service communication

图 4-2。 客户端到服务的直接通信

通过此方法,每项微服务都有一个前端客户端可访问的公共终结点。 在生产环境中,你将负载均衡器放在微服务前面,按比例路由流量。

虽然实现起来很简单,但只有简单的微服务应用程序可以接受客户端直接通信。 此模式将前端客户端紧密耦合到核心后端服务,带来了许多问题,包括:

  • 客户端对后端服务重构的敏感性。
  • 更广泛的攻击面,因为直接公开了核心后端服务。
  • 各项微服务中的横切关注点重复。
  • 过于复杂的客户端代码 - 客户端必须跟踪多个终结点,并以可复原的方式处理故障。

而广泛接受的云设计模式是在前端应用程序和后端服务之间实现 API 网关服务。 此模式如图 4-3 所示。

API Gateway Pattern

图 4-3。 API 网关模式

在上图中,请注意 API 网关服务如何抽象化后端核心微服务。 它以 Web API 的形式实现,充当“反向代理”,将传入流量路由到内部微服务。

网关可使客户端免受内部服务分区和重构的影响。 如果更改了后端服务,则无需中断客户端即可在网关中适应该服务。 这也是横切关注点(例如标识、缓存、复原能力、计量和限制)的第一道防线。 其中许多横切关注点可以从后端核心服务卸载到网关,从而简化后端服务。

必须谨慎操作,使 API 网关保持简单快速。 通常,业务逻辑会保留在网关外。 复杂的网关面临着变成瓶颈并最终成为单体应用本身的风险。 较大的系统通常会公开多个 API 网关,这些网关按客户端类型(移动、Web、桌面)或后端功能进行分段。 服务于前端的后端模式为多个网关的实现提供了一个方向。 此模式如图 4-4 所示。

Backend for Frontend Pattern

图 4-4。 服务于前端的后端模式

请注意上图中如何根据客户端类型(Web、移动或桌面应用)将传入流量发送到特定的 API 网关。 此方法很有意义,因为每个设备的功能因外形规格、性能和显示限制而截然不同。 通常,与浏览器或桌面应用程序相比,移动应用程序公开的功能更少。 可以优化每个网关,以匹配相应设备的能力和功能。

简单网关

首先,可以生成自己的 API 网关服务。 通过快速搜索 GitHub,可找到许多示例。

对于简单的 .NET 云原生应用程序,可考虑使用 Ocelot 网关。 它是为 .NET 微服务创建的开源网关,具有轻量、快速、可缩放的特点。 与任何 API 网关一样,其主要功能是将传入的 HTTP 请求转发到下游服务。 此外,它还支持各种可在 .NET 中间件管道中配置的功能。

YARP(另一种反向代理)是由一组 Microsoft 产品团队带领开发的另外一种开源反向代理。 可采用 NuGet 包的形式下载 YARP,它作为中间件插入到 ASP.NET 框架,可高度自定义。 你会发现 YARP 详细记录了各种用法示例。

对于企业云原生应用程序,有几项可帮助你快速开始工作的托管式 Azure 服务。

Azure 应用程序网关

对于简单的网关要求,可考虑使用 Azure 应用程序网关。 该网关作为 Azure PaaS 服务提供,它包含基本的网关功能(例如 URL 路由、SSL 终止和 Web 应用程序防火墙)。 该服务支持第 7 层负载均衡功能。 使用第 7 层,可以基于 HTTP 消息的实际内容(而不只是基于低级别的 TCP 网络数据包)路由请求。

在整本书中,我们都满腔热忱地宣传在 Kubernetes 中托管云原生系统。 作为容器业务流程协调程序,Kubernetes 可以自动化容器化工作负载的部署、缩放和操作性关注点。 Azure 应用程序网关可以配置为 Azure Kubernetes 服务群集的 API 网关。

应用程序网关入口控制器 让 Azure 应用程序网关能够直接使用 Azure Kubernetes 服务。 图 4.5 显示了相应的体系结构。

Application Gateway Ingress Controller

图 4-5。 应用程序网关入口控制器

Kubernetes 包含一项支持 HTTP(级别 7)负载均衡的内置功能,称为 Ingress。 Ingress 就如何向外部公开 AKS 中的微服务实例定义了一组规则。 在上图中,入口控制器解释为群集配置的入口规则,并自动配置 Azure 应用程序网关。 根据这些规则,应用程序网关将流量路由到 AKS 中运行的微服务。 入口控制器侦听对入口规则所做的更改,并相应地更改 Azure 应用程序网关。

Azure API 管理

对于中等规模到大规模的云原生系统,可考虑 Azure API 管理。 它是一项基于云的服务,不仅可以解决 API 网关需求,还提供功能完备的开发人员和管理体验。 API 管理如图 4-6 所示。

Azure API Management

图 4-6. Azure API 管理

首先,API 管理公开网关服务器,该服务器能够根据可配置的规则和策略对后端服务进行受控访问。 这些服务可以位于 Azure 云、本地数据中心或其他公有云中。 API 密钥和 JWT 令牌确定谁可以执行哪些操作。 所有流量都会被记录下来,用于分析目的。

API 管理为开发人员提供开发人员门户,通过该门户,可以访问服务、文档和示例代码,以便进行调用。 开发人员可以使用 Swagger/Open API 检查服务终结点并分析其使用情况。 该服务适用于各大主流开发平台:.NET、Java、Golang 等。

发布者门户公开了一个管理仪表板,管理员在其中公开 API 并管理其行为。 可以授予服务访问权限、监视服务运行状况,以及收集服务遥测数据。 管理员将策略应用于每个终结点来影响行为。 策略是针对每个服务调用按顺序执行的预生成语句。 可为入站和出站调用配置策略,也可在出现错误时调用策略。 可在不同的服务范围应用策略,以在组合策略时实现确定性排序。 该产品附带大量预生成的策略

下面的示例展示了策略如何影响云原生服务的行为:

  • 限制服务访问。
  • 强制执行身份验证。
  • 如有必要,限制来自单个源的调用。
  • 启用缓存。
  • 阻止来自特定 IP 地址的调用。
  • 控制服务的流。
  • 将请求从 SOAP 转换为 REST,或在不同的数据格式之间转换(例如从 XML 转换为 JSON)。

Azure API 管理可以公开托管在任意位置(在云或数据中心中)的后端服务。 对于可能在云原生系统中公开的旧服务,它支持 REST 和 SOAP API。 甚至其他 Azure 服务也可通过 API 管理公开。 可将托管的 API 放在 Azure 后备服务(如 Azure 服务总线Azure 逻辑应用)之上。 Azure API 管理不包括内置的负载均衡支持,应该与负载均衡服务结合使用。

Azure API 管理跨四个不同的层提供:

  • 开发人员
  • 基本
  • 标准
  • 高级

开发人员层用于非生产工作负载和评估。 其他层逐步提供更多能力、功能和更高的服务级别协议 (SLA)。 高级层提供 Azure 虚拟网络多区域支持。 所有层每小时都有固定价格。

Azure 云还为 Azure API 管理提供无服务器层。 该服务称为“消耗定价层”,是围绕无服务器计算模型设计的一种 API 管理变体。 与前面显示的“预分配”定价层不同,消耗层提供即时预配和按操作付费定价。

在以下用例中,它支持 API 网关功能:

  • 使用无服务器技术(如 Azure FunctionsAzure 逻辑应用)实现的微服务。
  • Azure 后备服务资源(如服务总线队列和主题、Azure 存储等)。
  • 流量偶尔出现较大峰值但多数时间保持在较低水平的微服务。

消耗层使用相同的底层服务 API 管理组件,但采用完全不同的体系结构(基于动态分配的资源)。 它与无服务器计算模型完全保持一致:

  • 没有要管理的基础结构。
  • 没有空闲容量。
  • 高可用性。
  • 自动缩放。
  • 成本基于实际使用情况。

对于将无服务器资源公开为 API 的云原生系统,新的消耗层是一个很好的选择。

实时通信

对于通过 HTTP 与后端云原生系统通信的前端应用程序,实时通信或推送通信是另一个选项。 应用程序(例如金融收报机、在线教育、游戏和作业进度更新)需要后端的即时实时响应。 使用正常的 HTTP 通信时,客户端无法获知新数据何时可用。 客户端必须持续轮询请求或向服务器发送请求。 如果使用实时通信,服务器就可以随时将新数据推送到客户端。

实时系统的特征通常是:高频数据流和大量并发客户端连接。 手动实现实时连接可能很快就会变得复杂,需要有意义的基础结构来确保可伸缩性以及向已连接的客户端的可靠消息传送。 你会发现自己正在管理 Azure Redis 缓存的实例和一组负载均衡器,这些负载均衡器配置了粘滞会话,用于进行客户端关联。

Azure SignalR 服务是完全托管的 Azure 服务,该服务可简化云原生应用程序的实时通信。 已省略容量预配、缩放和持久连接等技术实现详细信息。 它们按 99.9% 的服务级别协议进行处理。 你可专注于应用程序功能,而不是基础结构管道。

启用基于云的 HTTP 服务后,可将内容更新直接推送到已连接的客户端(包括浏览器、移动和桌面应用程序)。 无需轮询服务器即可更新客户端。 Azure SignalR 对创建实时连接的传输技术(包括 WebSockets、服务器端事件和长轮询)进行抽象化。 开发人员专注于将消息发送到已连接的客户端的所有或特定子集。

图 4-7 显示了一组 HTTP 客户端,这些客户端连接到启用了 Azure SignalR 的云原生应用程序。

Azure SignalR

图 4-7. Azure SignalR

Azure SignalR 服务的另一个优势是实现无服务器云原生服务。 也许代码是使用 Azure Functions 触发器按需执行的。 此方案可能比较棘手,因为代码不会与客户端保持长连接。 Azure SignalR 服务可以处理这种情况,因为该服务已为用户管理连接。

Azure SignalR 服务与其他 Azure 服务(例如 Azure SQL 数据库、服务总线或 Redis 缓存)紧密集成,为云原生应用程序提供了许多可能性。