微服务架构浅谈(二)

当决定将应用作为一组微服务时,需要决定应用客户端如何与微服务交互。在单体式程序中,通常只有一组冗余的或者负载均衡的服务提供点。在微服务 架构中,每一个微服务暴露一组细粒度的服务提供点。
介绍
假定你正在为在线购物应用开发一个原生手机客户端。你需要实现一个产品最终页来展示商品信息。
例如,下面的图展示了你在亚马逊Android客户端上滑动产品最终页时看到的信息。
微服务架构浅谈(二)_第1张图片
虽然这是一个智能手机应用,这个产品最终页展示了非常多的信息。例如,不仅这里有产品基本信息(名字、描述和价格),还有以下内容:
购物车中的物品数
下单历史
用户评论
低库存警告
快递选项
各式各样的推荐,包括经常跟这个物品一起被购买的产品、购买该物品的其他顾客购买的产品以及购买该产品的顾客还浏览了哪些产品。
当采用一个单体式应用架构,一个移动客户端将会通过一个REST请求(GET api.company.com/productdetails/productId)来获取这些数据。一个负载均衡将请求分发到多个应用实例之一。应用将查询各种数据库并返回请求给客户端。若是采用微服务架构,最终页上的数据会分布在不同的微服务上。
如果采用微服务架构,我们需要决定移动客户端如何访问这些服务。请看下面这几种方式
1、客户端到微服务直接通信
理论上说,一个客户端可以直接给多个为服务中的任何一个发送请求,每一个微服务会有一个对外的服务端,这个URL可能会映射到微服务的负载均衡上,然后转发请求到具体节点上,如上搜索产品细节,移动端需要向多个微服务逐个发送请求。
其中问题是客户端的需求量与每个微服务暴露的细粒度API数量不匹配。每个客户端的不同功能可能请求微服务的不同个和种服务,虽然一个客户端可以发情多个请求,但是这样效率很低,并且导致客户端代码非常复杂。
另外一个问题是客户端直接请求微服务的协议可能并不是web友好型,一个服务可能是用Thrift的RPC协议,另一个服务可能是用AMQP消息协议,他们都不是浏览器或防火墙友好的,并且最好是内部应用,应用应该在防火墙外采用类似HTTP或者WEBSocket协议。
还有另外一个缺点是很难重构微服务。随着时间的推移,我们可能需要改变系统微服务目前的切分方案。例如:我们科恩能够需要将多个服务合并或者将一个服务拆分为多个,但是如果客户端直接与微服务交互,那么这种重构就很难实施。
综上所述,客户端直接与服务器端通信的方式很少在实际中使用。
2、采用一个API Gateway
API Gateway是一个服务器,也可以说是进入系统的唯一节点。这跟面向对象设计模式中的Facet模式很像。API Gateway封装内部系统的架构,并且提供API给各个客户端。它还可能有其他功能,如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理等。 下图展示了一个适应当前架构的API Gateway。
微服务架构浅谈(二)_第2张图片
API Gateway负责请求转发、合成和协议转换。所有来自客户端的请求都要先经过API Gateway,然后路由这些请求到对应的微服务。API Gateway将经常通过调用多个微服务来处理一个请求以及聚合多个服务的结果。它可以在web协议与内部使用的非Web友好型协议间进行转换,如 HTTP协议、WebSocket协议。
API Gateway可以提供给客户端一个定制化的API。它暴露一个粗粒度API给移动客户端。以产品最终页这个使用场景为例。API Gateway提供一个服务提供点(/productdetails?productid=xxx)使得移动客户端可以在一个请求中检索到产品最终页的全 部数据。API Gateway通过调用多个服务来处理这一个请求并返回结果,涉及产品信息、推荐、评论等。
API Gateway 的优缺点
好处:封装应用内部结构。相比起来调用制定的服务,客户端直接跟gateway交互更加简单。并且API Gateway还给每一个客户端提供一个特定的API,这样减少了客户端与服务器端的通信次数,简化客户端代码
缺点:是一个高可用的组件,必须要开发,部署和管理。开发者必须更新它来提供新服务提供点来支持新暴露的微服务,更新API Gateway时必须越轻量级越好。
设计API Gateway需要考虑的事情
1、性能和可扩展性
对于大多数应用,API Gateway的性能和可扩展性也是非常重要的。因此,创建一个支持同步、非阻塞I/O的API Gateway是有意义的。一个可选的方案是 NGINX Plus。NGINX Plus提供一个成熟的、可扩展的、高性能web服务器和反向代理,它们均容易部署、配置和二次开发。NGINX Plus可以管理授权、权限控制、负载均衡、缓存并提供应用健康检查和监控。
2、采用反应性编程模型
对于有些请求,API Gateway可以通过直接路由请求到对应的后端服务上的方式来处理。对于另外一些请求,它需要调用多个后端服务并合并结果来处理。对于一些请求,例如产 品最终页面请求,发给后端服务的请求是相互独立的。为了最小化响应时间,API Gateway应该并发的处理相互独立的请求。但是,有时候请求之间是有依赖的。API Gateway可能需要先通过授权服务来验证请求,然后在路由到后端服务。类似的,为了获得客户的产品愿望清单,需要先获取该用户的资料,然后返回清单上 产品的信息。这样的一个API 组件是 Netflix Video Grid。
利用传统的同步回调方法来实现API合并的代码会使得你进入回调函数的噩梦中。这种代码将非常难度且难以维护。一个优雅的解决方案是采用反应性编程模式来实现。类似的反应抽象实现有Scala的 Future,Java8的 CompletableFuture和JavaScript的 Promise。基于微软.Net平台的有 Reactive Extensions(Rx)。Netflix为JVM环境创建了RxJava来使用他们的API Gateway。同样地,JavaScript平台有RxJS,可以在浏览器和Node.js平台上运行。采用反应编程方法可以帮助快速实现一个高效的API Gateway代码。
3、服务调用
一个基于微服务的应用是一个分布式系统,并且必须采用线程间通信的机制。有两种线程间通信的方法。一种是采用同步机制,基于消 息的方法。这类的实现方法有JMS和AMQP。另外的,例如Zeromq属于服务间直接通信。还有一种线程间通信采用异步机制,例如Thrift和 HTTP。事实上一个系统会同时采用同步和异步两种机制。由于它的实现方式有很多种,因此API Gateway就需要支持多种通信方式。
4、服务发现
API Gateway需要知道每一个微服务的IP和端口。在传统应用中,你可能会硬编码这些地址,但是在现在云基础的微服务应用中,这将是个简单的问题。基础服 务通常会采用静态地址,可以采用操作系统环境变量来指定。但是,探测应用服务的地址就没那么容易了。应用服务通常动态分配地址和端口。同样的,由于扩展或 者升级,服务的实例也会动态的改变。因此,API Gateway需要采用系统的服务发现机制,要么采用 服务端发现,要么是 客户端发现。
5、处理部分失败
在实现API Gateway过程中,还需要考虑部分失败,这个问题发生在分布式系统中当一个服务调用另外一个服务超时时或者不可用的情况。API Gateway不应该被阻断并处于无限期等待下游服务的状态,可以返回空或者部分信息。
在缓存有效的时候,API Gateway应该能够返回缓存。
Netflix Hystrix记录超过预设定的极限值的调用。它实现了circuit break模式,是的可以将客户端从无响应服务的无尽等待中停止,如果一个服务的错误率超过预设值,Hystrix将终端服务,并且在一段时间内所有请求立刻失效。Hystrix可以为请求失败定义一个fallback操作,例如:读取缓存或者返回默认值,尽可能考虑类似功能的库

总结:对于大多数微服务基础的应用,实现API Gateway是有意义的,它就像是进入系统的一个大门。API Gateway负责请求转发,请求合成和协议转换。它提供给应用客户端一个自定义的API。API Gateway可以通过返回缓存或者默认值的方式来掩盖后端服务的错误。

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