克里斯·理查森(ChrisRichardson)。
编辑-这个由七部分组成的系列文章现已完成:
您还可以下载完整的文章集,以及有关使用Nginx Plus作为电子书实现微服务的信息-微服务:从设计到部署.另外,请看新的微服务解决方案页面.
本系列由七部分组成的第一篇文章。关于设计、构建和部署微服务,介绍了MicroServicesArchitecture模式。它讨论了使用微服务的优点和缺点,以及尽管微服务的复杂性,它们通常是复杂应用程序的理想选择。这是本系列的第二篇文章,将讨论使用API网关构建微服务。
当您选择将应用程序构建为一组微服务时,您需要决定应用程序的客户端将如何与微服务交互。对于单块应用程序,只有一组(通常是复制的、负载平衡的)端点。然而,在微服务体系结构中,每个微服务公开了一组典型的细粒度端点。在本文中,我们将研究这如何影响客户端到应用程序的通信,并提出了一种使用API网关.
让我们想象一下,您正在为一个购物应用程序开发一个本地移动客户端。您可能需要实现一个产品详细信息页面,该页面显示任何给定产品的信息。
例如,下图显示了在Amazon的Android移动应用程序中滚动产品详细信息时所看到的内容。
尽管这是一个智能手机应用程序,但产品详细信息页面显示了大量信息。例如,不仅有基本的产品信息(如名称、描述和价格),而且这个页面还显示:
当使用单块应用程序体系结构时,移动客户端将通过发出一个REST调用来检索这些数据(GET
api.company.com/productdetails/productId
)的申请。负载平衡器将请求路由到N个相同的应用程序实例之一。然后,应用程序将查询各种数据库表,并将响应返回给客户端。
相反,当使用微服务体系结构时,显示在产品详细信息页面上的数据属于多个微服务。下面是一些潜在的微服务,它们拥有在示例产品详细信息页面上显示的数据:
我们需要决定移动客户端如何访问这些服务。让我们看看选择。
理论上,客户端可以直接向每个微服务提出请求。每个微服务都有一个公共端点(https:/serviceName.api.company.name)此URL将映射到微服务的负载均衡器,后者在可用实例中分发请求。要检索产品详细信息,移动客户端将向上面列出的每个服务发出请求。
不幸的是,这一选择存在挑战和局限性。一个问题是客户端的需求与每个微服务公开的细粒度API之间的不匹配。本例中的客户端必须发出七个单独的请求。在更复杂的应用程序中,它可能需要制造更多的应用程序。例如,Amazon描述了如何使用数百个服务来呈现其产品页面。虽然客户端可以在局域网上提出这么多请求,但在公共互联网上可能效率太低,而且在移动网络上肯定是不切实际的。这种方法还使客户端代码更加复杂。
客户端直接调用微服务的另一个问题是,有些用户可能使用不适合网络的协议。一个服务可能使用ThwigueBinaryRPC,而另一个服务可能使用AMQP消息传递协议。这两种协议都不是特别的浏览器或防火墙友好,最好在内部使用。应用程序应该在防火墙之外使用HTTP和WebSocket等协议。
这种方法的另一个缺点是很难重构微服务。随着时间的推移,我们可能希望改变系统被划分为服务的方式。例如,我们可以合并两个服务或将一个服务拆分为两个或多个服务。但是,如果客户端直接与服务通信,那么执行这种重构是非常困难的。
由于这类问题,客户直接与微服务交谈是很难理解的。
通常,更好的方法是使用所谓的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网关有好处也有缺点。使用APIGateway的一个主要好处是它封装了应用程序的内部结构。客户端不必调用特定的服务,只需与网关对话。APIGateway为各种客户端提供了特定的API。这减少了客户机和应用程序之间往返的次数。它还简化了客户端代码。
API网关也有一些缺点。它是另一个必须开发、部署和管理的高度可用的组件。API网关也有成为开发瓶颈的风险。开发人员必须更新API网关,以便公开每个微服务的端点。更新APIGateway的过程必须尽可能轻量级。否则,开发人员将被迫排队等待更新网关。然而,尽管存在这些缺点,但对于大多数实际应用程序来说,使用APIGateway是有意义的。
现在我们已经研究了使用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网关还可以通过返回缓存或默认数据来掩盖后端服务中的故障。在本系列的下一篇文章中,我们将讨论服务之间的通信。
编辑-这个由七部分组成的系列文章现已完成:
您还可以下载完整的文章集,以及有关使用Nginx Plus作为电子书实现微服务的信息-微服务:从设计到部署.
有关其他用例的详细信息,请参阅我们的三部分博客系列,将Nginx Plus部署为API网关: