使用API网关构建微服务

Posted IT技术精选文摘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用API网关构建微服务相关的知识,希望对你有一定的参考价值。

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


介绍 


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


例如,下图显示了在亚马逊的android移动应用程序中滚动产品详细信息时将看到的内容。

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

       购物车中的商品数量 

       订单历史 

       顾客评论 

       低库存警告 

       送货选项 

       各种建议,包括本产品经常购买的其他产品,购买此产品的客户购买的其他产品,以及购买该产品的客户查看的其他产品 

       其他购买选择


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


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

      购物车服务 - 购物车中的商品数量 

      订单服务 - 订单历史记录 

      目录服务 - 基本的产品信息,如其名称,图像和价格 

      评论服务 - 客户评论 

      库存服务 - 库存警告低 

      运输服务 - 运输选择,截止日期和与运输提供商的API分开的费用 

      推荐服务 - 建议的项目

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


客户端到微服务的直接通信 


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


不幸的是,这个选项有挑战和限制。其中的一个问题是客户端的需求与每个微服务公开的细粒度API不匹配。此示例中的客户端必须进行七个单独的请求。在更复杂的应用中,它可能需要做更多的工作。例如,亚马逊描述了如何将数百项服务纳入其产品页面。虽然客户端可以通过LAN发出许多请求,但是对于公共互联网来说,这可能是太低效率的,并且在移动网络上肯定是不切实际的。这种方法也使客户端代码复杂得多。 


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


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


由于这些问题,客户直接与微服务进行通信没有什么意义。


使用API网关 


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


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

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


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


API Gateway的一个很好的例子是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服务器和反向代理,易于部署,配置和编程。 NGINX Plus可以管理身份验证,访问控制,负载均衡请求,缓存响应,并提供应用感知的健康检查和监控。


使用反应式编程模型 


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


使用传统的异步回调方法编写API组合代码很快会将您的回调带入地狱。代码会纠缠不清,难以理解,容易出错。一个更好的方法是使用反应性方法以声明式编写API网关代码。反应抽象的例子包括未来的Scala,Java 8中的CompletableFuture和JavaScript中的Promise。还有Reactive Extensions(也称为Rx或ReactiveX),最初由Microsoft为.NET平台开发。 Netflix为JVM创建了RxJava,专门用于其API网关。还有用于JavaScript的RxJS,它们都在浏览器和Node.js中运行。使用反应式方法将使您能够编写简单而有效的API网关代码。


服务调用 


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


服务发现 



处理部分失效 


实现API网关时必须解决的另一个问题是部分故障的问题。每当一个服务调用另一个缓慢响应或不可用的服务时,所有分布式系统都会出现此问题。 API网关不应无限期地等待下游服务。但是,如何处理故障取决于特定方案和哪些服务失败。例如,如果推荐服务在产品详细信息方案中无响应,则API网关应将剩余的产品详细信息返回给客户端,因为它们对用户仍然有用。建议可以是空的,也可以由例如硬编码的前十名列表替代。但是,如果产品信息服务无响应,则API网关应向客户端返回错误。  


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


Netflix Hystrix是一个令人难以置信的有用的库,用于编写调用远程服务的代码。 Hystrix对超出指定阈值的请求进行超时限制。它实现了断路器模式,这阻止了客户端不必要地等待无响应的服务。如果服务的错误率超过指定的阈值,Hystrix将跳闸断路器,所有请求将在指定的时间内立即失败。 Hystrix允许您在请求失败时定义回退操作,例如从缓存读取或返回默认值。如果您使用的是JVM,那么您一定要考虑使用Hystrix。而且,如果您运行在非JVM环境中,则应使用等效的库。 


总结


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

以上是关于使用API网关构建微服务的主要内容,如果未能解决你的问题,请参考以下文章

0102-使用 API 网关构建微服务

.net core 微服务之Api网关(Api Gateway)

微服务从设计到部署使用 API 网关

使用 Node.js 构建 API 网关

API网关和微服务通信

客户端可以绕过API网关调用前端微服务吗?