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

原文链接:Building Microservices: Using an API Gateway


介绍

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

尽管只是移动APP,商品详情页依然展示给我们很多信息,不仅包括基本信息(名称、描述、价格),还包含如下内容:

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

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

对应如果采用微服务架构,展示在产品详情页的数据会来自不同的微服务上。下面列举一些微服务对应的展示数据:

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

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

客户端与服务端直接通信

理论上客户端可以直接请求每个微服务,每个微服务都有一个公开的节点(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,还可以通过返回默认值或缓存值来处理后端服务的调用失败。下篇文章,我们将讨论服务间的通信。

Chris Richardson微服务翻译:构建微服务之使用API网关的更多相关文章

  1. Chris Richardson微服务翻译:微服务部署

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服务部署( ...

  2. Chris Richardson微服务翻译:微服务之事件驱动的数据管理

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理(本文) 微服 ...

  3. Chris Richardson微服务翻译:微服务架构中的服务发现

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现(本文) 微服务之事件驱动的数据管理 微服 ...

  4. 微服务系列(二):使用 API 网关构建微服务

    编者的话|本文来自 Nginx 官方博客,是微服务系列文章的第二篇,本文将探讨:微服务架构是如何影响客户端到服务端的通信,并提出一种使用 API 网关的方法. 作者介绍:Chris Richardso ...

  5. Chris Richardson微服务翻译:微服务介绍

    作者简介:Chris Richardson,世界著名的软件架构师,经典著作<POJOS IN ACTION>的作者,cloudfoundry.com 的创始人 微服务目前正受到大量的关注, ...

  6. 实测 | 转型微服务,这4大工具谁是API网关性能最优?

    转自:http://www.servicemesh.cn/?/article/45 作者:Turgay Çelik 翻译:钟毅(Drew Zhong) 原文:Comparing API Gateway ...

  7. NET Core微服务之路:基于Ocelot的API网关Relay实现--RPC篇

    前言 我们都知道,API网关是工作在应用层上网关程序,为何要这样设计呢,而不是将网关程序直接工作在传输层.或者网络层等等更底层的环境呢?让我们先来简单的了解一下TCP/IP的五层模型.     (图片 ...

  8. Chris Richardson微服务翻译:构建微服务之微服务架构的进程通讯

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯(本文) 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服 ...

  9. Chris Richardson微服务翻译:重构单体服务为微服务

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服务部署 ...

随机推荐

  1. 【CODEFORCES】 A. Dreamoon and Sums

    A. Dreamoon and Sums time limit per test 1.5 seconds memory limit per test 256 megabytes input stand ...

  2. xml概述(1)

    本节要点: 标记语言的定义 XML简介 XML与HTML 比较 XML与数据库比较 XML的特点 XML结构 1 标记语言的定义 "XML.SGML.HTML"中的"ML ...

  3. Java的单例模式

    单例模式:单例模式确保其一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式又分为:懒汉式,饿汉式等; 特点: a.单例只有一个实例. b.必须自己创建自己唯一的实例 c.单例类必须 ...

  4. Windows 10 安装 Docker for Windows

    Docker for Windows是Docker社区版(CE)应用程序. Docker for Windows安装包包括在Windows系统上运行Docker所需的一切. 本主题介绍了预安装注意事项 ...

  5. Java filter中的chain

    一.Filter Filter:用来拦截请求,处于客户端和被请求资源之间,是为了代码的复用性.Filter链,在web.xml中哪个先配置就先调用哪个 二.FilterChain(过滤链) 服务器会按 ...

  6. 管道设计CAD系统中重量重心计算

    管道设计CAD系统中重量重心计算 eryar@163.com Abstract. 管道设计CAD系统中都有涉及到重量重心计算的功能,这个功能得到的重心数据主要用于托盘式造船时方便根据重心设置吊装配件. ...

  7. 《编程语言实现模式》【PDF】下载

    <编程语言实现模式> 编程语言实现模式旨在传授构建语言应用(工具)的经验和理念,教读者构建自己的语言应用.这里的语言应用并非特指用编译器或解释器实现编程语言,而是泛指任何处理.分析.翻译输 ...

  8. 《奇思妙想:15位计算机天才及其重大发现》【PDF】下载

    <奇思妙想:15位计算机天才及其重大发现>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196328 内容简介 本书介绍了15位当代 ...

  9. iOS 正则表达式使用(转)

    1/ 教程一:认识正则表达式 .http://deerchao.net/tutorials/regex/regex.htm#mission 表7.尚未详细讨论的语法 代码/语法 说明 \a 报警字符( ...

  10. Servlet小总结

    Servlet Servlet(服务器端小程序)是使用Java语言编写的服务器端程序,像JSP一样,生成动态的Web页.Servlet主要运行在服务器端,并由服务器调用执行. Servlet处理的基本 ...