当你选择采用微服务构建自己的程序,则你需要考虑客户端怎样与后端服务交互。对于一个单体应用,仅有一个服务群提供服务(通过负载均衡器实现)。在微服务架构里面,每一个服务都暴漏了一个服务器集群。本篇文章我们讨论它对于客户端通讯的影响和提出通过API网关的解决办法。
背景介绍
首先让我们想象一下一个购物的移动程序。它需要实现产品详情页展示,例如产品信息、库存信息、订单信息、购物车等。例如,下图显示了你将看到的产品信息:
尽管它仅仅是一个手机程序的详情页,它也显示了产品的一些信息。它不仅展示了一些产品的基本信息(名称、描述和价格),也显示以下信息:
1)购物车中的产品数
2)订单历史
3)客户浏览历史
4)低库存预警
5)物流信息
6)推荐信息,包括经常购买的新、购买过之后的推荐和浏览历史推荐;
7)不同的购买选项
如果采用单体程序,客户端仅仅需要一个链接就能够获取所需要的所有信息。负载均衡器返回任何一个应用程序的反馈数据即可。应用程序将会查询数据表,并向客户返回数据。
相反,微服务架构下,产品详情页数据则需要好几个服务群才能够提供。这里是几个拥有产品详情页信息数据的几个服务器服务:
1)购物车服务-负责显示购物车中的产品数量
2)订单服务-订单历史
3)类目服务-提供产品的名字、描述和价格
4)历史服务-用户的浏览历史
5)库存服务-低库存预警
6)物流服务-从物流提供商返回物流花费、到达时间和物流选项
7)推荐服务-建议选项
我们需要决定,客户端怎样获取这些服务。下面让我们讨论一下可能的方案。
客户端直接连接微服务
理论上微服务可以直接连接微服务。每一个微服务都有一个地址,这个地址映射向服务均衡(提供服务的负载)地址。为了获取产品信息,客户端可以直接连接上述的微服务地址。
不幸的,这种方案存在挑战和限制。其一,其存在客户端和微服务之间的错配问题。客户端不得不发起其次独立的请求。在复杂的系统,它需要返回更多的请求。例如,亚马逊在选择页面的时候描述了数百个微服务。如果客户端发起了过多的请求,会导致 互联网的低效,这也不是移动网络的最佳实践。这也会导致客户端的过度复杂。(个人觉得,如果微服务页面较少,这会提升开发效率和网络请求时间)
直连的另一个问题是微服务对外的协议可能不是web友好的。例如,有些服务采用Thrift binary RPC,而有些则采用AMQP 。这两种协议都不是浏览器和防火墙所友好的协议。一个友好的web协议应该采用WebSocket 或者HTTP协议。
另一个缺陷是这种解决方案使得重构微服务变得困难。随着时间改变,我们想改变微服务划分的标准。例如,我们可能将两个微服务合并,或者拆分一个微服务。这种类型的重构将会使得这种方案变得非常困难。
采用API网关
通常,一个较好的方案采用API网关。API网关是一种从前端到后端的唯一路径服务。它类似于面向对象设计的 Facade 模式。API网关将后端的服务进行了包装,同时提供了客户端所需要的API。它还提供其他职责,像权限、监控、负载均衡、缓存、请求转发和管理、静态请求处理等。
以下图展示了API网关适应的架构:
API网关负责请求的路由转发、组合和协议解释。所有来自客户端的请求都需要经过API网关。它将请求匹配到合适的微服务。它通过请求多个微服务或者聚合结果处理请求。它能够在HTTP、WebSocket和不友好的协议之间转换。
API网关也为客户端提供个性化的接口。它为移动客户端提供了粗粒度的API。例如,产品的详情页。例如,他能够为移动客户端提供一个连接,通过此可以获得所有的所需数据。API网关处理请求分为两步:1)向不同的服务请求数据 2)合并数据。