Chris Richardson微服务翻译:构建微服务之使用API网关

Chris Richardson 微服务系列翻译全7篇连接:html

原文连接:Building Microservices: Using an API Gateway
java


介绍

假设咱们为一个商品应用开发一个移动APP,咱们应该提供一个产品详情页来展现指定产品的信息。Amazon Android 应用在商品详情页展现的内容,以下图所示:react

尽管只是移动APP,商品详情页依然展现给咱们不少信息,不只包括基本信息(名称、描述、价格),还包含以下内容:nginx

  • 购物车中的商品数
  • 历史订单记录
  • 买家评价
  • 低库存预警
  • 送货选项
  • 推荐:包括与此商品一块儿购买的其余商品、购买该商品的顾客还买的其余商品、购买该商品的顾客还看过其余的商品
  • 其余购物选项

使用单体应用架构时,移动APP经过单一的 REST 请求(GET api.company.com/productdetails/productId)来获取展现的数据。负载均衡会将请求路由到多个相同实例的其中一个,而后程序查询各类数据库表,返回数据给客户端。git

对应若是采用微服务架构,展现在产品详情页的数据会来自不一样的微服务上。下面列举一些微服务对应的展现数据:github

  • 购物车服务:购物车中的商品数
  • 订单服务:订单记录
  • 目录服务:商品基本信息,如名称、图片和价格
  • 评论服务:用户评价
  • 库存服务:低库存预警
  • 配送服务:送货选项、期限和费用
  • 推荐服务:推荐商品

客户端如何访问这些服务,让咱们看看下面的方法。web

客户端与服务端直接通讯

理论上客户端能够直接请求每一个微服务,每一个微服务都有一个公开的节点(https://serviceName.api.company.com),该 URL 映射到负载均衡,而后被分发到可用的实例上处理,为了获取产品详情,移动客户端须要向上述每一个服务发送请求。数据库

遗憾的是,这种方法存在挑战和局限:编程

1)客户端需求和每一个微服务暴露出的细粒度 API 不匹配。本例中客户端须要发送7个不一样的请求,在一个复杂的应用中请求数甚至还要更多,例如亚马逊在显示他们的产品页面时会调用数百个服务。这种方法还使得客户端代码很是复杂。后端

2)一些服务使用的协议对 web 并不友好。一个服务可能使用 Thrift 的二进制 RPC,而另外一个服务可能使用 AMQP 消息协议。这些协议不是浏览器和防火墙友好的,最好在内部使用。而防火墙以外,应用程序最好使用 HTTP 或 WebSocket 之类的协议。

3)这种方法会使得微服务难以重构。随着时间的推移,咱们可能要从新规划、合并或拆分微服务,若是客户端直接与微服务通讯的话,对这些微服务进行重构变得异常困难。

正是这些缘由,采用客户端直接调用微服务的方式并不明智。

使用 API 网关

一般更好的方式是使用 API 网关,API 网关是提供系统惟一入口的服务器,他和设计模式中的 外观模式 相似:API 网关封装内部系统架构,并向客户端提供 API。它还可能负责诸如 用户验证、监控、负载均衡、缓存、请求管理、静态响应处理等功能。下图展现了适应 API 网关的架构:

API 网关负责请求路由、组合和协议转换。来自客户端的全部请求都先通过 API 网关,而后被路由到对应的微服务中,API 网关一般调用多个微服务并聚合其结果来处理请求。它能够在 web 协议(如 HTTP 和 WebSocket)与内部使用的非 web 协议之间转换。

API 网关能够为每一个客户端提供定制的 API,它一般为移动客户端暴露粗粒度的 API。例如:商品详情页,API 网关提供 (/productdetails?productid=xxx) 节点使得移动客户端单一请求能够获取全部的产品明细。API 网关调用各个服务(商品信息、推荐、评论等)合并结果并返回。

Netflix API网关 就是一个很好的 API 网关实例。Netflix 流媒体服务提供给成百上千的设备使用,包括电视、机顶盒、智能手机、游戏系统、平板电脑等。最初,Netflix 视图为他们的流服务提供通用的 API,然而,他们发现因为设备的独特需求,这种设计方式不能很好的工做。现在他们使用 API 网关经过运行设备的适配器代码为客户端提供定制的 API,一般适配器为每一个请求平均调用6~7个微服务,Netflix API网关天天处理数十亿请求。

使用 API 网关的优点及劣势

使用 API 网关有优点也有不足。

最大优势是:
1)它封装了应用的内部结构,客户端只须要简单的与 API 网关交互便可,而不用直接调用每一个服务。
2)API 网关为不一样的客户端提供定制的 API,减小了客户端和应用间的交互次数,并大大简化了客户端的代码。

API 网关也有其不足:
1)它自己增长了一个须要开发、部署和维护的高可用组件。
2)API 网关有时候变成了开发的瓶颈。开发者为了暴露新的微服务必须更新 API 网关。API 网关的更新流程要尽量的简单,不然,开发人员不得不排队等待。尽管它有这些不足,但对于大部分的应用程序而言,使用 API 网关是合理的。

实现一个 API 网关

目前咱们讨论了 API 网关的动机和一些优缺点。下面咱们看一些须要考虑的一些设计问题。

性能与扩展性

只有少数公司拥有 Netflix 这样的规模,天天须要处理数十亿的请求。对于大多数程序而言,API 网关的性能和可扩展性是很是重要的。所以,API 网关构建在一个支持异步、IO 非阻塞的平台上是合理的。有多种不一样的技术可参考:JVM 上,基于 NIO 的框架,好比 Netty、Vertx、 Spring Reactor 或 JBoss Undertow 等。一个流行的选项是 Node.js,他是构建于 Chrome JS 引擎的平台。另外一个选项是 NGINX Plus,他提供了成熟、可扩展、高性能的 web 服务器和一个易于部署的、可配置可编程的反向代理。NGINX Plus 能够管理身份验证、权限控制、负载均衡、缓存以及应用级别的健康检查及监控。

使用响应式编程模型

API 网关将请求路由到相应的多个微服务并合并处理结果,对于一些请求,例如产品详情页,后端对应的服务是彼此独立的,为了减小响应时间,API 网关应并行处理这些请求。然而有时候,请求之间是有依赖关系的,在请求微服务以前,API 网关须要调用身份验证服务来验证请求的合法性。相似的,获取用户心愿单上的产品信息时,API 网关须要先获取包含这些信息的客户资料,而后再去获取信息的详情。另外一个有趣的例子就是:Netflix Video Grid

使用传统的异步回调方式来写 API 组合代码会把你带入地狱。代码会变的混乱、难以理解且容易出错。更好的方式是使用响应式方法,以一种声明式样式编写 API 网关代码。例如:Scala中的 Future 、Java 8中的 CompletableFuture 以及JavaScript中的 Promise,还有微软为.NET开发的 Reactive Extensions。Netflix 为他们的 API 网关建立了 RxJava for JVM,此外还有 RxJS for JavaScript,既能够在浏览器中运行,也能够在Node.js 中运行。响应式风格将帮助你写出简洁高效的 API 网关代码。

服务调用

微服务架构是一个进程间通讯的分布式系统, 有两种进程间通讯方式:一种是采用异步、基于消息传递的机制。例如:JMS 或 AMQP 这样的消息组件;另外一种是使用 HTTP 或 Thrfit 这种同步机制进行通讯。一般,一个系统会同时使用同步和异步方式,甚至还会使用同一类型的多种实现。总之,API 网关须要支持不一样的通讯机制。

服务发现

API 网关须要知道和他通讯的每一个微服务的地址(IP和端口号)。传统应用中,可使用硬编码的方式,可是在现代基于云的微服务应用中,这不是一个容易解决的问题。基础架构服务(例如:消息组件)一般会有一个静态地址,能够在环境变量中指定。然而,获取一个微服务地址就不是简单的事了,微服务的地址是动态分配的,一组服务实例可能由于自动扩展或升级而动态的变化。所以 API 网关须要服务发现机制,能够是服务器端发现,或者是客户端发现(后面的文章会详细介绍服务发现的问题)。若是使用客户端发现的话,API 网关应该能查询服务注册中心,这是一个包含全部微服务实例及其地址的数据库。

处理局部故障

局部故障在分布式系统中很常见,当一个服务调用另外一个服务,当后者响应慢或不可用时就出现了这个问题。API 网关不能由于无限期的等待下游服务而阻塞。不过,如何处理失败取决于应用场景或具体哪一个服务失败,例如:产品详情页,推荐服务挂了,那么 API 网关应该返回其余产品信息,保障产品对用户仍然可用,推荐内容可为空或使用固定的 Top 10 列表取代。不过,若是产品服务挂了,那么 API 网关应该返回客户端错误信息。

API 网关也能够缓存返回的数据。例如:产品价格变更不频繁,当价格服务不可用时,API 网关能够返回缓存的价格数据。数据能够是 API 网关本身缓存,也可使用 Redis 或 Memcached之类的外部缓存。经过返回默认值或缓存值,API 网关保证局部故障不会影响用户体验。

Netflix Hystrix 在编写代码调用远程服务时是很是有用的,Hystrix 会标记超过特定阀值的调用为超时,他还实现了『熔断器』模式来防止对无响应服务的更多请求,若是一个服务的出错率超过了特定阀值,那么 Hystrix 会触发熔断器,全部请求会快速失败并持续一段时间。Hystrix 容许用户定义请求失败时的 fallback 操做,例如:读取缓存或返回默认值。若是你在使用 JVM ,那么应该考虑使用 Hystrix,若是使用的是非 JVM 环境,那么可使用一个功能相同的库。

总结

对于大部分基于微服务的应用,实现 API 网关做为应用的单一入口是明智的。API 网关负责请求路由、聚合、协议转换。为每一个客户端提供特定的 API,还能够经过返回默认值或缓存值来处理后端服务的调用失败。下篇文章,咱们将讨论服务间的通讯。

相关文章
相关标签/搜索