1. 微服务介绍
  2. 构建微服务:使用API​​网关(本文)
  3. 构建微服务:微服务架构中的进程间通信
  4. 微服务架构中的服务发现
  5. 事件驱动的数据管理微服务
  6. 选择微服务部署策略
  7. 将重组重构为微服务

您还可以下载完整的文章集,以及使用NGINX Plus实现微服务的信息,作为电子书 -微服务:从设计到部署

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

当您选择将应用程序构建为一组微服务时,您需要决定应用程序的客户端将如何与微服务进行交互。对于单片应用程序,只有一组(通常是复制的,负载平衡的)端点。然而,在微服务架构中,每个微服务暴露一组通常是细粒度端点的。在本文中,我们研究这如何影响客户端到应用程序的通信,并提出使用API网关的方法

介绍

让我们假设您正在为购物应用程序开发本地移动客户端。您可能需要实施产品详情页面,其中显示有关任何指定产品的信息。

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

即使这是一个智能手机应用程序,产品详细信息页面显示了很多信息。例如,不仅有基本的产品信息(如名称,说明和价格),但此页面还显示:

  • 购物车中的商品数量
  • 订单历史
  • 顾客评论
  • 低库存警告
  • 运输选项
  • 各种建议,包括该产品经常购买的其他产品,购买此产品的客户购买的其他产品,以及购买此产品的客户查看的其他产品
  • 其他采购选择

当使用单片应用程序架构时,移动客户端将通过对应用程序进行单个REST调用()来检索此数据。负载平衡器将请求路由到N个相同的应用程序实例之一。然后应用程序将查询各种数据库表,并将响应返回给客户端。GETapi.company.com/productdetails/productId

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

  • 购物车服务 - 购物车中的商品数量
  • 订单服务 - 订单历史记录
  • 目录服务 - 基本产品信息,如其名称,图像和价格
  • 评论服务 - 客户评论
  • 库存服务 - 低库存警告
  • 装运服务 - 装运选项,截止日期和费用与装运提供商的API分开绘制
  • 推荐服务 - 建议的项目

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

直接客户端到微服务通信

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

不幸的是,这个选项有挑战和限制。一个问题是客户端的需求与每个微服务公开的细粒度API之间的不匹配。在这个例子中的客户端必须做七个单独的请求。在更复杂的应用程序中,它可能需要做更多。例如,Amazon描述了如何在呈现其产品页面中涉及数百种服务。虽然客户端可以通过LAN进行这么多请求,但是它可能在公共互联网上太低效,并且对于移动网络肯定是不切实际的。这种方法也使得客户端代码更复杂。

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

这种方法的另一个缺点是它使重构微服务变得困难。随着时间的推移,我们可能希望改变系统如何划分为服务。例如,我们可以合并两个服务或将服务分为两个或更多服务。然而,如果客户直接与服务通信,则执行这种重构可能是非常困难的。

由于这些类型的问题,客户端很少直接与微服务交谈。

使用API​​网关

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

下图显示了API网关通常如何适应该架构:

API网关负责请求路由,组合和协议转换。来自客户端的所有请求首先通过API网关。然后它将请求路由到适当的微服务。API网关通常会通过调用多个微服务并聚合结果来处理请求。它可以在Web协议(如HTTP和WebSocket)和内部使用的Web不友好协议之间进行转换。

API网关还可以为每个客户端提供自定义API。它通常为移动客户端提供粗粒度的API。例如,考虑产品详细情况。API网关可以提供端点(/ productdetails?productid =xxx),使移动客户端能够通过单个请求检索所有产品详细信息。API网关通过调用各种服务(产品信息,建议,评论等)并结合结果来处理请求。

API网关的一个很好的例子是Netflix API网关。Netflix流媒体服务可用于数百种不同类型的设备,包括电视,机顶盒,智能手机,游戏系统,平板电脑等。最初,Netflix试图为其流媒体服务提供一种一刀切的API。然而,他们发现,它不能很好地工作,因为各种各样的设备及其独特的需求。今天,他们使用API​​网关,通过运行特定于设备的适配器代码为每个设备提供定制的API。适配器通常通过调用平均六到七个后端服务来处理每个请求。Netflix API网关每天处理数十亿次请求。

API网关的优点和缺点

正如您所期望的,使用API​​网关具有优点和缺点。使用API​​网关的一个主要好处是它封装了应用程序的内部结构。客户端只需要与网关通话,而不必调用特定的服务。API网关为每种类型的客户端提供特定的API。这减少了客户端和应用程序之间的往返次数。它还简化了客户端代码。

API网关也有一些缺点。它是另一个高度可用的组件,必须开发,部署和管理。还有一个风险是API网关成为开发瓶颈。开发人员必须更新API网关才能公开每个微服务的端点。重要的是,更新API网关的过程尽可能轻量级。否则,开发人员将被迫排队等待以更新网关。尽管有这些缺点,然而,对于大多数现实世界的应用程序,使用API​​网关是有意义的。

实现API网关

现在我们已经研究了使用API​​网关的动机和权衡,让我们来看看您需要考虑的各种设计问题。

性能和可扩展性

只有少数公司在Netflix的规模运营,每天需要处理数十亿的请求。然而,对于大多数应用程序,API网关的性能和可扩展性通常非常重要。因此,在支持异步,非阻塞I / O的平台上构建API网关是有意义的。有多种不同的技术可以用于实现可扩展的API网关。在JVM上,您可以使用基于NIO的框架之一,如Netty,Vertx,Spring Reactor或JBoss Undertow。一个流行的非JVM选项是Node.js,它是一个基于Chrome的JavaScript引擎的平台。另一个选择是使用NGINX Plus。NGINX Plus提供了一个成熟的,可扩展的高性能Web服务器和反向代理,易于部署,配置和编程。

使用反应式编程模型

API网关通过将它们简单地路由到适当的后端服务来处理一些请求。它通过调用多个后端服务并聚合结果来处理其他请求。对于某些请求,例如产品详细信息请求,对后端服务的请求是彼此独立的。为了最小化响应时间,API网关应同时执行独立请求。然而,有时,请求之间存在依赖关系。API网关可能首先需要在将请求路由到后端服务之前通过调用身份验证服务来验证请求。类似地,为了获取关于顾客的愿望清单中的产品的信息,API网关必须首先检索包含该信息的顾客的简档,然后检索每个产品的信息。

使用传统的异步回调方法编写API组合代码快速导致回调地狱。代码将会纠缠,难以理解,并且容易出错。一个更好的方法是使用反应式方法以声明样式编写API网关代码。反应抽象的例子包括未来在Scala中,CompletableFuture在Java中8,并承诺在JavaScript中。还有反应式扩展(也称为Rx或ReactiveX),它最初是由Microsoft为.NET平台开发的。Netflix为专门在其API网关中使用的JVM创建了RxJava。还有用于JavaScript的RxJS,它在浏览器和Node.js中都运行。

服务调用

基于微服务的应用是分布式系统,并且必须使用进程间通信机制。有两种风格的进程间通信。一个选项是使用基于消息传递的异步机制。一些实现使用消息代理,例如JMS或AMQP。其他,如Zeromq,是无代理的,服务直接通信。另一种类型的进程间通信是诸如HTTP或Thrift之类的同步机制。系统通常使用异步和同步样式。它甚至可以使用每个样式的多个实现。因此,API网关将需要支持各种通信机制。

服务发现

API网关需要知道它与之通信的每个微服务的位置(IP地址和端口)。在传统的应用程序中,您可能可以将位置固定连接,但在现代的基于云的微服务应用程序中,这是一个非常重要的问题。基础设施服务(例如消息代理)通常具有静态位置,可以通过OS环境变量指定。然而,确定应用服务的位置不是那么容易。应用程序服务具有动态分配的位置。此外,服务的实例集合由于自动缩放和升级而动态地改变。因此,API网关与系统中的任何其他服务客户端一样需要使用系统的服务发现机制:服务器端发现客户端发现。一个以后的文章中会详细描述了服务发现。现在,值得注意的是,如果系统使用客户端发现,那么API网关必须能够查询服务注册表,它是所有微服务实例及其位置的数据库。

处理部分故障

您在实现API网关时必须解决的另一个问题是部分失败的问题。每当一个服务调用另一个响应缓慢或不可用的服务时,在所有分布式系统中都会出现此问题。API网关不应阻止无限期地等待下游服务。然而,它如何处理故障取决于具体情况和哪个服务失败。例如,如果推荐服务在产品细节场景中没有响应,则API网关应将其余产品细节返回给客户端,因为它们对用户仍然有用。建议可以是空的,或者由例如硬连接的十大列表替换。然而,如果产品信息服务无响应,那么API网关应该向客户端返回错误。

API网关还可以返回缓存数据(如果可用)。例如,由于产品价格很少更改,如果定价服务不可用,API网关可以返回高速缓存的定价数据。数据可以由API网关本身缓存或存储在外部缓存(如Redis或Memcached)中。通过返回默认数据或缓存数据,API网关确保系统故障不会影响用户体验。

NetflixHystrix是一个非常有用的库,用于编写调用远程服务的代码。Hystrix会超出超过指定阈值的呼叫。它实现了断路器模式,其阻止客户端不必要地等待无响应的服务。如果服务的错误率超过指定的阈值,Hystrix将断开断路器,并且所有请求将在指定的时间段内立即失败。Hystrix允许您在请求失败时定义回退操作,例如从高速缓存读取或返回默认值。如果你使用JVM,你一定要考虑使用Hystrix。并且,如果您在非JVM环境中运行,则应使用等效库。

概要

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

编辑 - 这七个系列的文章现在完成:

  1. 微服务介绍
  2. 构建微服务:使用API​​网关(本文)
  3. 构建微服务:微服务架构中的进程间通信
  4. 微服务架构中的服务发现
  5. 事件驱动的数据管理微服务
  6. 选择微服务部署策略
  7. 将重组重构为微服务

results matching ""

    No results matching ""