第8章 外部API模式
前言
不同客户端通常需要不同数据;不同客户端通过不同类型的网络访问服务,拥有单一、适合所有客户端的API通常没有意义;
这是一本关于微服务架构设计方面的书,这是本人阅读的学习笔记。下面对一些符号做些说明:
()为补充,一般是书本里的内容;
[]符号为笔者笔注;
1. 外部API的设计难题
1.1 FTGO应用程序的服务及客户端
- 使用服务API的客户端一共有四种:
- Web应用程序;
- 在浏览器中运行的JavaScript应用程序;
- 移动应用程序;
- 由第三方开发人员编写的应用程序;
- 其弊端有:
- 细颗粒度服务API要求客户端发出多个请求以检索所需的数据,这样做效率低,并且可能导致糟糕的用户体验;
- 由于客户端了解每项服务以及服务的API从而导致封装不足(紧耦合),因此今后很难更改服务的架构和API;
- 服务可能适用对客户端而言不便或不能使用的进程间通信机制,尤其是防火墙外的客户端;
1.2 FTGO移动客户端API的设计难题
上述设计方案难处在于:
- 多次客户端请求导致用户体验不佳 [考虑到移动网络的时延与多次请求的耗电量];
- 缺乏封装导致前端开发做出的代码修改影响后端 [有时会破坏现有客户端来修改API,导致旧版本不兼容];
- 服务可能选用对客户端不友好的进程间通信机制 [有些协议无法通过防火墙];
1.3 其他类型客户端API的设计难题与特点
- Web应用程序的API设计特点:
- 有较高的网络带宽和较低的延迟;
- 可以使用非Web友好的协议访问服务;
- 可以轻松更新Web应用程序;
- 基于浏览器JavaScript应用程序的API设计特点与难题:
- 服务API变化时,基于浏览器JavaScript应用程序很容易更新;
- 与移动端有相同的网络延迟问题;
- 基于浏览器的用户界面,需要组合更多服务;
- 为第三方应用程序设计API:
- 组合API导致低效率;
- 必须花长时间维护旧版本;
2. API Gateway模式
使用API Gateway模式可以解决上述问题;
- API Gateway模式:实现一个服务,该服务是外部API客户端进入基于微服务应用程序的入口点;
2.1 API Gateway实现的功能
2.1.1 请求路由
- 收到请求时,API Gateway会查询路由映射,该映射指定将请求路由到哪个服务;
2.1.2 API组合
- 其提供粗颗粒度API,使移动客户端能够通过单个请求检索所需的数据;
2.1.3 协议转换
- 在需要时,某些API的操作实现在RESTful外部API和基于内部的gRPC API之间进行转换;
2.1.4 能够为每一个客户端提供它们专用的API
- 可以为Android和iPhone移动应用程序提供不同的API,还将为第三方开发人员实现公共API;
2.1.5 实现边缘功能
- 可以在三个不同位置实现边缘功能:
- 在后端服务:相较于边缘上进行身份验证不安全;
- 在API Gateway上游的边缘服务:好处是可以分隔问题、集中关键边缘功能的职责;弊端是额外的请求跳跃增加网络延迟状况、增加程序复杂性;
- 在API Gateway中实现边缘服务:可以减少网络跳跃、改善延迟状况、降低复杂性;提高安全性,详情见【第11章 API Gateway与服务协作实现安全性】;
- 边缘功能:
- 身份验证:验证发出请求的客户端身份;
- 访问授权:验证客户端是否有权执行该特定操作;
- 速率限制:限制特定客户或所有客户端每秒的请求数;
- 缓存:缓存响应以减少对服务的请求数;
- 指标收集:收集有关API使用情况的指标,以进行计费分析;
- 请求日志:记录请求历史;
2.2 API Gateway的架构
图解:
- 两层架构:
- API层:由一个或多个独立的API模块组成;
- 公共层:实现共享功能、边缘功能,如身份验证;
- 三个API模块:
- 移动设备API:为FTGO移动客户端实现API;
- 浏览器API:为浏览器中运行的JavaScript应用程序实现API;
- 公共API:为第三方开发人员实现API;
- 使用两种方式实现每个API操作:
- 直接映射到单个服务API操作;
- 使用组合实现其他复杂API操作;
2.3 API Gateway的所有者模式
- 客户端团队拥有与他们有关的API模块并公开API;
- API Gateway团队负责开发公共模块和API Gateway的运维;
- API Gateway的部署流水线必须完全自动化;否则,客户端团队不得不等待API Gateway团队手工部署一个新的版本;
- 问题:多个团队为相同的代码库做贡献,职责模糊;
- 解决办法:使用后端前置模式
2.4 API Gateway的后端前置模式
- 后端前置模式:为每种类型的客户端实现单独的API Gateway;
- 理想情况下,所有API Gateway都使用相同的技术栈;
- 公共层的功能由API Gateway团队实现;
- 好处:明确界定职责、API彼此隔离提高可靠性、提高可观测性、每个API独立可扩展、减少启动时间;
2.5 API Gateway模式的好处与弊端
好处:
- 封装应用程序的内部;
- 减少客户端与应用程序之间的往返次数;
- 简化客户端代码;
弊端:
- 开发人员必须更新API Gateway才能对外公开服务的API;
- 更新API Gateway的过程尽可能轻量化;
2.6 API Gateway的设计难题
- 性能和可扩展性:影响性能和可扩展性的关键设计决策是API Gateway使用同步还是异步I/O;
- 同步I/O:每个网络连接由专用线程处理;限制是操作系统线程是重量级的,API Gateway可拥有的线程数量和并发连接数量存在上限;
- 异步(非阻塞)I/O:单个事件循环线程将I/O请求分派给事件处理程序;具有可扩展性;弊端是比基于异步回调的编程模型要复杂得多,代码更难编写、理解和调试;使用非阻塞I/O是否具有意义的整体优势取决于API Gateway的请求处理逻辑特性;
- 使用响应式编程抽象编写可维护的代码:
- 当服务之间没有依赖关系时,应该尽可能同时调用服务,以缩短响应时间;
- 使用传统的异步回调方法编写API组合代码会导致“回调地狱”,可以以声明式风格编写API组合代码;
- 处理局部故障:
- 可以在负载均衡器后面运行多个API Gateway实例实现可靠性;
- 对于失败服务未完成的请求可以使用断路器模式提高可靠性,详情见【第3章 断路器模式】;
- 成为应用程序架构中的好公民:
- 与其他服务一样API Gateway必须实现整个架构中选择的各种模式;
- 如:服务发现模式【第三章】;可观测性模式【第十一章】;
3. 实现一个API Gateway
3.1 实现API Gateway的两种方法
- 使用现成的API Gateway产品或服务:几乎不需要代码开发,但灵活性最低;如:现成的API Gateway通常不支持API组合;
- 使用API Gateway框架或Web框架作为起点,开发属于自己的API Gateway:最灵活的方法,但需要进行一些开发工作;
3.2 使用现成的API Gateway产品或服务
- AWS API Gateway
- AWS Application Load Balancer
- 使用产品化的API Gateway;
3.3 使用Netflix Zuul开发API Gateway
- 开发API Gateway需要解决两个问题:
- 实现定义路由规则的机制以简化复杂的代码;
- 正确实现HTTP代理行为,包括如何处理HTTP标头;
- Zuul使用过滤器的概念,可重用请求拦截器;
- Zuul通过一系列适用的过滤器来处理HTTP请求,然后转换请求,调用后端服务,并在响应发送回客户端之前转换响应;
- 限制:它只能实现基于路径的路由,无法实现【第7章】描述的查询架构;
3.4 使用Spring Cloud Gateway开发API Gateway
- Spring Cloud Gateway是一个基于多个框架构建的API Gateway框架,属于响应式Web框架,构建在Project Reactor之上;
- Project Reactor是一个基于NIO的JVM响应式框架;
- 其提供一种简单而全面的方法执行以下操作:
- 将请求路由到后端;
- 实现执行API组合的请求处理程序;
- 处理边缘功能,例如身份验证;
3.5 Spring Cloud Gateway的关键部分
图解:
- ApiGatewayMain包:定义API Gateway的主程序;
- 一个或多个API包:一个API包实现一组API端点;如,Orders包实现与Order相关的API端点;
- 代理程序包:由API程序包用于调用服务的代理类组成;
- OrderConfiguration类:定义了一些Spring beans,它们负责路由与Order相关的请求;
- orderProxyRoutes @Bean:定义了将API操作映射到后端服务URL的规则;路由规则可以匹配HTTP方法、标头和路径的某些组合;
- orderHandlers @Bean:定义了覆盖orderProxyRoutes的规则;这些规则描述了将API操作映射到处理程序的具体方法;
- orderHandlers类:实现各种请求处理程序方法,此方法使用API组合来获取订单详细信息;处理程序的方法使用远程代理类(如OrderService)调用后端服务;
3.5.1 OrderConfiguration类
-
OrderConfiguration类是一个Spring @Configuration类,它定义了实现 /Orders端点的Spring @Bean;
-
OrderDestinations是一个Spring @ConfigurationProperties类,它支持后端服务URL的外部配置;
3.5.2 OrderHandlers类
- OrderHandlers类定义了实现自定义行为的请求处理程序方法,包括API组合;
3.5.3 OrderService类
- OrderService类是Order Service的远程代理;
3.5.4 ApiGatewayApplication类
- ApiGatewayApplication类实现了API Gateway的main()方法,它是Spring Boot main类;
- @EnableGateway注解导入Spring Cloud Gateway框架的Spring配置;
3.6 使用GraphQL实现API Gateway
GraphQL是一种基于图像的API框架,其旨在支持高效的数据提取;
图解:
- 基于图形的模式定义了一组节点(类型),它们具有属性(字段)和其他节点的关系;
3.7 基于GraphQL的FTGO API Gateway的设计
其关键部分:
- GraphQL模式:定义服务器端数据模型及其支持的查询;
- 解析器函数:解析函数将模式的元素映射到各种后端服务;
- 代理类:代理类调用FTGO应用程序的服务;
4. 本章小结
- 应用程序的外部客户端通常利用API Gateway访问应用程序的服务。API Gateway为每个客户端提供自定义API。它负责请求路由、API组合、协议转换以及边缘功能(如身份验证)的实现;
- 应用程序可以具有单个API Gateway,也可以使用后端前置模式,该模式为每种类型的客户端定义API Gateway。后端前置模式的主要优点是它为客户端团队提供了更大的自主权,因为他们可以开发、部署和运维自己的API Gateway;
- 可以使用许多种技术来实现API Gateway,包括现成的API Gateway产品。或者,也可以使用框架开发自己的API Gateway;
- Spring Cloud Gateway是一个易于使用的良好框架,用于开发API Gateway。它使用任何属性(包括方法和路径)路由请求。Spring Cloud Gateway可以将请求直接路由到后端服务或自定义处理程序方法。它采用可扩展、响应式的Spring Framework 5 和Project Reactor框架构建。可以使用,例如,Project Reactor的Mono抽象,以响应式风格编写自定义请求处理程序;
- GraphQL是一个提供基于图形的查询语言框架,是开发API Gateway的另一个很好的基础。你可以编写一个面向图形的模式来描述服务端数据模型及其支持的查询。然后,通过编写检索数据的解析器,将该模式映射到你的服务。基于GraphQL的客户端对模式执行查询,该模式准确指定服务器应返回的数据。因此基于GraphQL的API Gateway可以支持不同的客户端;