构建微服务:使用API网关

 

构建微服务:使用API网关

 

 

克里斯·理查森(ChrisRichardson)。

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

 

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

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

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

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

导言

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

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

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

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

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

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

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

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

直接客户对微服务通信

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

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

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

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

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

使用API网关

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

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

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网关。

 

你可能感兴趣的:(java,微服务)