【编者的话】本pd的第一介l了微服务架构模式。它讨论了采用微服务的优点和~点Q除了一些复杂的微服务,q种模式q是复杂应用的理想选择?/span>
当你军_应用作Zl微服务Ӟ需要决定应用客L如何与微服务交互。在单体式程序中Q通常只有一l冗余的或者负载均衡的服务提供炏V在微服务架构中Q每一个微服务暴露一l细_度的服务提供点。在本篇文章中,我们来看它如何媄响客L到服务端通信Q同时提ZUAPI Gateway的方法?/span>
介绍
假定你正在ؓ在线购物应用开发一个原生手机客L。你需要实C个品最l页来展C商品信息?/span>
例如Q下面的囑ֱCZ你在亚马逊Android客户端上滑动产品最l页时看到的信息?/span>
虽然q是一个智能手机应用,q个产品最l页展示了非常多的信息。例如,不仅q里有品基本信息(名字、描q和hQ,q有以下内容Q?/span>
- 购物车中的物品数
- 下单历史
- 用户评论
- 低库存警?/li>
- 快递选项
- 各式各样的推荐,包括l常跟这个物品一赯购买的品、购买该物品的其他顾客购买的产品以及购买该品的֮q浏览了哪些产品?/li>
- 可选的购物选项
当采用一个单体式应用架构Q一个移动客L会通过一个RESThQGET api.company.com/productdetails/productIdQ来获取q些数据。一个负载均衡将h分发到多个应用实例之一。应用将查询各种数据库ƈq回hl客L?/span>
相对的,若是采用微服务架构,最l页上的数据会分布在不同的微服务上。下面列举了可能与品最l页数据有关的一些微服务Q?/span>
- 购物车服?-- 购物车中的物品数
- 下单服务 -- 下单历史
- 分类服务 -- 基本产品信息Q如名字、图片和h
- 评论服务 -- 用户评论
- 库存服务 -- 低库存警?/li>
- 快递服?-- 快递选项、截止时间、来自不同快递API的成本计?/li>
- 推荐服务 -- 推荐产品
我们需要决定移动客L如何讉Kq些服务。请看下面这几种方式
客户端到微服务直接通信
理论上说Q一个客L可以直接l多个微服务中的M一个发赯求。每一个微服务都会有一个对外服务端(https://serviceName.api.company.name)。这个URL可能会映到微服务的负蝲均衡上,它再转发h到具体节点上。ؓ了搜索品细节,Ud端需要向上述微服务逐个发请求?/span>
不幸的是Q这个方案有很多困难和限制。其中一个问题是客户端的需求量与每个微服务暴露的细_度API数量的不匚w。如图中Q客L需?ơ单独请求。在更复杂的场景中,可能会需要更多次h。例如,亚马逊的产品最l页要请求数百个微服务。虽然一个客L可以通过LAN发v很多个请求,但是在公|上q样会很没有效率Q这个问题在Ud互联|上ؓH出。这个方案同时会D客户端代码非常复杂?/span>
另一个存在的问题是客L直接h微服务的协议可能q不是web友好型。一个服务可能是用Thrift的RPC协议Q而另一个服务可能是用AMQP消息协议。它们都不是览或防火墙友好的,q且最好是内部使用。应用应该在防火墙外采用cMHTTP或者WEBSocket协议?/span>
q个Ҏ的另一个缺Ҏ它很N构微服务。随着旉的推U,我们可能需要改变系l微服务目前的切分方案。例如,我们可能需要将两个服务合ƈ或者将一个服务拆分ؓ多个。但是,如果客户端直接与微服务交互,那么q种重构很隑֮施?/span>
׃上述三种问题的原因,客户端直接与服务器端通信的方式很在实际中用?/span>
采用一个API Gateway
API Gateway的优点和~点
如你所料,采用API Gateway也是优缺点ƈ存的。API Gateway的一个最大好处是装应用内部l构。相比v来调用指定的服务Q客L直接跟gatway交互更简单点。API Gateway提供l每一个客L一个特定APIQ这样减了客户端与服务器端的通信ơ数Q也化了客户端代码?/span>
API Gateway也有一些缺炏V它是一个高可用的组Ӟ必须要开发、部|和理。还有一个问题,它可能成为开发的一个瓶颈。开发者必L新API Gateway来提供新服务提供Ҏ支持新暴露的微服务。更新API Gateway时必越轻量U越好。否则,开发者将因ؓ更新Gateway而排队列。但是,除了q些~点Q对于大部分的应用,采用API Gateway的方式都是有效的?/span>
实现一个API Gateway
既然我们已经知道了采用API Gateway的动机和优缺点,下面来看在设计它旉要考虑哪些事情?/span>
性能和可扩展?/h4>只有数公司需要处理像Netflix那样的规模,每天需要处理数十亿的请求。但是,对于大多数应用,API Gateway的性能和可扩展性也是非帔R要的。因此,创徏一个支持同步、非dI/O的API Gateway是有意义的。已l有不同的技术可以用来实C个可扩展的API Gateway。在JVM上,采用ZNIO技术的框架Q如NettyQVertxQSpring Reactor或者JBoss Undertow。Node.js是一个非JVM的流行^収ͼ它是一个在Chrome的JavaScript引擎基础上徏立的q_。一个可选的Ҏ?/span>NGINX Plus。NGINX Plus提供一个成熟的、可扩展的、高性能web服务器和反向代理Q它们均Ҏ部v、配|和二次开发。NGINX Plus可以理授权、权限控制、负载均衡、缓存ƈ提供应用健康查和监控?/span>
采用反应性编E模?/h4>对于有些hQAPI Gateway可以通过直接路由h到对应的后端服务上的方式来处理。对于另外一些请求,它需要调用多个后端服务ƈ合ƈl果来处理。对于一些请求,例如产品最l页面请求,发给后端服务的请求是怺独立的。ؓ了最化响应旉QAPI Gateway应该q发的处理相互独立的h。但是,有时候请求之间是有依赖的。API Gateway可能需要先通过授权服务来验证请求,然后在\由到后端服务。类似的Qؓ了获得客L产品愿望清单Q需要先获取该用L资料Q然后返回清单上产品的信息。这L一个API lg?/span>Netflix Video Grid?/span>
利用传统的同步回调方法来实现API合ƈ的代码会使得你进入回调函数的噩梦中。这U代码将非常隑ֺ且难以维护。一个优雅的解决Ҏ是采用反应性编E模式来实现。类似的反应抽象实现有Scala?/span>FutureQJava8?/span>CompletableFuture和JavaScript?/span>Promise。基于微?Netq_的有Reactive Extensions(Rx)。Netflix为JVM环境创徏了RxJava来用他们的API Gateway。同样地QJavaScriptq_有RxJSQ可以在览器和Node.jsq_上运行。采用反应编E方法可以帮助快速实C个高效的API Gateway代码?/span>
服务调用
一个基于微服务的应用是一个分布式pȝQƈ且必采用线E间通信的机制。有两种U程间通信的方法。一U是采用异步机制Q基于消息的Ҏ。这cȝ实现Ҏ有JMS和AMQP。另外的Q例如Zeromq属于服务间直接通信。还有一U线E间通信采用同步机制Q例如Thrift和HTTP。事实上一个系l会同时采用同步和异步两U机制。由于它的实现方式有很多U,因此API Gateway需要支持多U通信方式?/span>
服务发现
处理部分p|
在实现API Gatewayq程中,另外一个需要考虑的问题就是部分失败。这个问题发生在分布式系l中当一个服务调用另外一个服务超时或者不可用的情cAPI Gateway不应该被Lq处于无限期{待下游服务的状态。但是,如何处理q种p|依赖于特定的场景和具体服务。例如,如果是在产品详情늚推荐服务模块无响应,那么API Gateway应该q回剩下的其他信息给用户Q因些信息也是有用的。推荐部分可以返回空Q也可以q回固定的顶?0个给用户。但是,如果是品信息服务无响应Q那么API Gateway应该给客户端返回一个错误?/span>
在缓存有效的时候,API Gateway应该能够q回~存。例如,׃产品h变化q不频繁QAPI Gateway在h格服务不可用时应该返回缓存中的数倹{这cL据可以由API Gateway自n来缓存,也可以由Redis或Memcachedq类外部~存实现。通过q回~存数据或者默认数据,API Gateway来确保系l错误不影响到用户体验?/span>
Netflix Hystrix对于实现q程服务调用代码来说是一个非常好用的库。Hystrix记录那些过预设定的极限值的调用。它实现?/span>circuit break模式Q得可以将客户端从无响应服务的无尽{待中停止。如果一个服务的错误率超q预讑ր|Hystrix中断服务,q且在一D|间内所有请求立d效。Hystrix可以求失败定义一个fallback操作Q例如读取缓存或者返回默认倹{如果你在用JVMQ就应该考虑使用Hystrix。如果你采用的非JVM环境Q那么应该考虑采用cM功能的库?/span>
ȝ
对于大多数微服务基础的应用,实现一个API Gateway都是有意义的Q它像是进入系l的一个服务提供点。API Gateway负责h转发、请求合成和协议转换。它提供l应用客L一个自定义的API。API Gateway可以通过q回~存或者默认值的方式来掩盖后端服务的错误。在本系列的下一文章中Q我们将讨论服务间的通信问题?/span>
原文链接Q?a style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;">Building Microservices: Using an API Gateway (译Q陈李ͼ审校Q杨?
===============================================
译者介l?/span>
陈杰Q北京理工大学计机学院在读博士Q研I方向是自然语言处理在企业网l信誉评h面的应用Q^时也乐于dC些突发的x。在疲于配置pȝ环境时发CDockerQ跟大家一起学习、用和研究Docker?/span>

]]>