构建微服务:使用API网关

 

构建微服务:使用API网关

 

Tags

 

克里斯·理查森(ChrisRichardson)。html

编辑-这个由七部分组成的系列文章现已完成:java

 

 您还能够下载完整的文章集,以及有关使用Nginx Plus做为电子书实现微服务的信息-微服务:从设计到部署.另外,请看新的微服务解决方案页面.react

  1. 微服务导论
  2. 构建微服务:使用API网关
  3. 构建微服务:微服务体系结构中的进程间通讯
  4. 微服务体系结构中的服务发现
  5. 事件驱动的微服务数据管理
  6. 选择Microservices部署策略
  7. 将Monolith重构为MicroServices

本系列由七部分组成的第一篇文章。关于设计、构建和部署微服务,介绍了MicroServicesArchitecture模式。它讨论了使用微服务的优势和缺点,以及尽管微服务的复杂性,它们一般是复杂应用程序的理想选择。这是本系列的第二篇文章,将讨论使用API网关构建微服务。nginx

当您选择将应用程序构建为一组微服务时,您须要决定应用程序的客户端将如何与微服务交互。对于单块应用程序,只有一组(一般是复制的、负载平衡的)端点。然而,在微服务体系结构中,每一个微服务公开了一组典型的细粒度端点。在本文中,咱们将研究这如何影响客户端到应用程序的通讯,并提出了一种使用API网关.git

导言

让咱们想象一下,您正在为一个购物应用程序开发一个本地移动客户端。您可能须要实现一个产品详细信息页面,该页面显示任何给定产品的信息。github

例如,下图显示了在Amazon的Android移动应用程序中滚动产品详细信息时所看到的内容。web

Indexed elements of Amazon's mobile app for Android, as they appear on a mobile phone screen

尽管这是一个智能手机应用程序,但产品详细信息页面显示了大量信息。例如,不只有基本的产品信息(如名称、描述和价格),并且这个页面还显示:数据库

  • 购物车中物品的数量
  • 秩序史
  • 客户评论
  • 低库存警告
  • 航运选择
  • 各类建议,包括本产品常用的其余产品,购买此产品的客户购买的其余产品,以及购买此产品的客户查看的其余产品。
  • 可供选择的采购方案

当使用单块应用程序体系结构时,移动客户端将经过发出一个REST调用来检索这些数据(GET api.company.com/productdetails/productId)的申请。负载平衡器将请求路由到N个相同的应用程序实例之一。而后,应用程序将查询各类数据库表,并将响应返回给客户端。编程

相反,当使用微服务体系结构时,显示在产品详细信息页面上的数据属于多个微服务。下面是一些潜在的微服务,它们拥有在示例产品详细信息页面上显示的数据:后端

  • 购物车服务-购物车中的物品数量
  • 订单服务-订单历史记录
  • 目录服务-基本产品信息,如名称、形象和价格
  • 评审服务-客户评审
  • 库存服务-低库存警告
  • 航运服务-运输选项、截止日期和成本分别从航运供应商的API中提取
  • 建议处-建议项目

Mobile client of ecommerce app needs a way to access the RESTful APIs of the 7 microservices

咱们须要决定移动客户端如何访问这些服务。让咱们看看选择。

直接客户对微服务通讯

理论上,客户端能够直接向每一个微服务提出请求。每一个微服务都有一个公共端点(https:/serviceName.api.company.name)此URL将映射到微服务的负载均衡器,后者在可用实例中分发请求。要检索产品详细信息,移动客户端将向上面列出的每一个服务发出请求。

不幸的是,这一选择存在挑战和局限性。一个问题是客户端的需求与每一个微服务公开的细粒度API之间的不匹配。本例中的客户端必须发出七个单独的请求。在更复杂的应用程序中,它可能须要制造更多的应用程序。例如,Amazon描述了如何使用数百个服务来呈现其产品页面。虽然客户端能够在局域网上提出这么多请求,但在公共互联网上可能效率过低,并且在移动网络上确定是不切实际的。这种方法还使客户端代码更加复杂。

客户端直接调用微服务的另外一个问题是,有些用户可能使用不适合网络的协议。一个服务可能使用ThwigueBinaryRPC,而另外一个服务可能使用AMQP消息传递协议。这两种协议都不是特别的浏览器或防火墙友好,最好在内部使用。应用程序应该在防火墙以外使用HTTP和WebSocket等协议。

这种方法的另外一个缺点是很难重构微服务。随着时间的推移,咱们可能但愿改变系统被划分为服务的方式。例如,咱们能够合并两个服务或将一个服务拆分为两个或多个服务。可是,若是客户端直接与服务通讯,那么执行这种重构是很是困难的。

因为这类问题,客户直接与微服务交谈是很难理解的。

使用API网关

一般,更好的方法是使用所谓的API网关。API网关是一个服务器,它是进入系统的单一入口点。它相似于立面从面向对象的设计模式。API网关封装了内部系统架构,并提供了针对每一个客户端的API。它可能还有其余职责,如身份验证、监视、负载平衡、缓存、请求整形和管理以及静态响应处理。

下图显示了API网关一般如何适合体系结构:

An API gateway enables mobile clients of ecommerce app to access the RESTful APIs of its 7 microservices

API网关负责请求路由、组合和协议转换。来自客户端的全部请求首先经过API网关。而后,它将请求路由到适当的微服务。API网关一般经过调用多个微服务并聚合结果来处理请求。它能够在HTTP和WebSocket等Web协议和内部使用的Web不友好协议之间进行转换。

API网关还能够为每一个客户端提供一个自定义API。它一般为移动客户端公开粗粒度API。例如,考虑一下产品细节场景。API网关能够提供端点(/产品细节?产量d=某某),使移动客户端可以使用单个请求检索全部产品详细信息。API网关经过调用各类服务(产品信息、建议、评论等)来处理请求。-并结合结果。

API网关的一个很好的例子是Netflix API网关。Netflix流媒体服务能够在数百种不一样的设备上使用,包括电视机、机顶盒、智能手机、游戏系统、平板电脑等。最初,Netflix试图提供一个一体式他们的流媒体服务的API。然而,他们发现,因为设备的多样性和它们独特的需求,它并不能很好地工做。今天,他们使用了一个api网关,经过运行特定于设备的适配器代码,为每一个设备提供一个api。适配器一般经过平均调用6到7个后端服务来处理每一个请求。NetflixAPI网关天天处理数十亿次请求。

API网关的优缺点

正如您可能预期的那样,使用API网关有好处也有缺点。使用APIGateway的一个主要好处是它封装了应用程序的内部结构。客户端没必要调用特定的服务,只需与网关对话。APIGateway为各类客户端提供了特定的API。这减小了客户机和应用程序之间往返的次数。它还简化了客户端代码。

API网关也有一些缺点。它是另外一个必须开发、部署和管理的高度可用的组件。API网关也有成为开发瓶颈的风险。开发人员必须更新API网关,以便公开每一个微服务的端点。更新APIGateway的过程必须尽量轻量级。不然,开发人员将被迫排队等待更新网关。然而,尽管存在这些缺点,但对于大多数实际应用程序来讲,使用APIGateway是有意义的。

实现API网关

如今咱们已经研究了使用API网关的动机和权衡,让咱们看看您须要考虑的各类设计问题。

性能和可伸缩性

只有少数几家公司以Netflix的规模运营,天天须要处理数十亿的请求。然而,对于大多数应用程序来讲,API网关的性能和可伸缩性一般是很是重要的。所以,在支持异步、非阻塞I/O的平台上构建API网关是有意义的。有多种不一样的技术可用于实现可伸缩的API网关。在JVM上,您可使用基于NIO的框架之一,如Netty、Vertx、Spring反应堆或JBossUnder拖车。Node.js是一个流行的非JVM选项,它是一个构建在Chrome JavaScript引擎上的平台。另外一个选择是使用Nginx Plus。Nginx Plus提供了一个成熟的、可伸缩的、高性能的Web服务器和反向代理,它易于部署、配置和编程。Nginx Plus能够管理身份验证、访问控制、负载平衡请求、缓存响应,并提供应用程序感知的健康检查和监视。

使用反应性编程模型

API网关经过将请求路由到适当的后端服务来处理某些请求。它经过调用多个后端服务并聚合结果来处理其余请求。对于某些请求,例如产品详细信息请求,对后端服务的请求是相互独立的。为了减小响应时间,API网关应该同时执行独立的请求。然而,有时请求之间存在依赖关系。在将请求路由到后端服务以前,API网关可能首先须要经过调用身份验证服务来验证请求。相似地,要在客户愿望列表中获取有关产品的信息,API网关必须首先检索包含该信息的客户配置文件,而后检索每一个产品的信息。另外一个有趣的api组合示例是Netflix视频网格.

使用传统的异步回调方法编写API组合代码很快就会致使回调地狱。代码将混乱,难以理解,而且容易出错。更好的方法是使用反应性方法以声明式方式编写API网关代码。反应性抽象的示例包括将来在斯卡拉,圆满的将来在Java 8中,以及承诺用JavaScript写的。也有反应性扩展(也称为Rx或ReactiveX),最初是由Microsoft为.NET平台开发的。Netflix为JVM建立了RxJava,专门用于其API网关。还有用于JavaScript的RxJS,它运行在浏览器和Node.js中。使用反应性方法将使您可以编写简单而高效的API网关代码。

服务调用

基于微服务的应用程序是一个分布式系统,必须使用进程间通讯机制.过程间交流有两种方式.一种选择是使用异步的、基于消息传递的机制。有些实现使用消息代理,如JMS或AMQP。还有一些,如Zeromq,是无经纪人的,服务直接通讯。进程间通讯的另外一种方式是一种同步机制,如HTTP或Thspace。系统一般同时使用异步和同步样式。它甚至可使用每种样式的多个实现。所以,API网关须要支持各类通讯机制。

服务发现

API网关须要知道与其通讯的每一个微服务的位置(IP地址和端口)。在传统应用程序中,您可能会硬链接位置,可是在一个现代的、基于云的微服务应用程序中,这是一个很是重要的问题。基础设施服务(如MessageBroker)一般具备静态位置,能够经过OS环境变量指定该位置。然而,肯定应用程序服务的位置并不容易。应用程序服务具备动态分配的位置。此外,因为自动标度和升级,服务实例集会动态更改。所以,与系统中的任何其余服务客户端同样,API网关须要使用系统的服务发现机制:服务器端发现客户端发现。一个后文将更详细地描述服务发现。如今,值得注意的是,若是系统使用客户端发现,则api网关必须可以查询服务登记处,它是全部微服务实例及其位置的数据库。

处理部分故障

实现API网关时必须解决的另外一个问题是部分失败的问题。每当一个服务调用另外一个响应缓慢或不可用的服务时,全部分布式系统都会出现此问题。API网关不该该无限期地阻止等待下游服务。然而,它如何处理故障取决于特定的场景和哪一个服务正在失败。例如,若是推荐服务在产品详细信息场景中没有响应,则API网关应该将其他的产品详细信息返回给客户端,由于它们对用户仍然有用。这些建议要么是空的,要么被硬连线的前十名取代。可是,若是产品信息服务没有响应,那么API网关应该向客户端返回一个错误。

若是数据可用,API网关也能够返回缓存的数据。例如,因为产品价格变化不频繁,若是订价服务不可用,API网关能够返回缓存的订价数据。数据能够由API网关自己缓存,也能够存储在外部缓存中,如Redis或memcached。经过返回默认数据或缓存数据,API网关确保系统故障不会影响用户体验。

Netflix hystrix是一个很是有用的库,用于编写调用远程服务的代码。hystrix超时超过指定阈值的调用。它实现了断路器模式,它阻止客户端没必要要地等待无响应的服务。若是服务的错误率超过了指定的阈值,hystrix将触发断路器,全部请求都将在指定的时间内当即失败。hystrix容许您在请求失败时定义回退操做,例如从缓存读取或返回默认值。若是您正在使用JVM,那么必定要考虑使用hystrix。并且,若是您在非JVM环境中运行,则应该使用等效的库。

摘要

对于大多数基于微服务的应用程序来讲,实现API网关是有意义的,它做为进入系统的单一入口点。API网关负责请求路由、组合和协议转换。它为每一个应用程序的客户端提供一个自定义API。API网关还能够经过返回缓存或默认数据来掩盖后端服务中的故障。在本系列的下一篇文章中,咱们将讨论服务之间的通讯。

编辑-这个由七部分组成的系列文章现已完成:

  1. 微额服务简介
  2. 构建微服务:使用API网关(本文)
  3. 构建微服务:微服务体系结构中的进程间通讯
  4. 微服务体系结构中的服务发现
  5. 事件驱动的微服务数据管理
  6. 选择Microservices部署策略
  7. 将Monolith重构为MicroServices

您还能够下载完整的文章集,以及有关使用Nginx Plus做为电子书实现微服务的信息-微服务:从设计到部署.

有关其余用例的详细信息,请参阅咱们的三部分博客系列,将Nginx Plus部署为API网关:

  • 第一部分为几个用例提供详细的配置说明。
  • 第二部分扩展这些用例,并查看可应用于在生产中保护和保护后端API服务的一系列安全措施。
  • 第3部分解释如何将Nginx Plus部署为GRPC服务的API网关。