首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Chris Richardson微服务翻译:构建微服务之使用API网关

Chris Richardson微服务翻译:构建微服务之使用API网关

作者头像
butterfly100
发布2018-04-17 12:11:21
8180
发布2018-04-17 12:11:21
举报
文章被收录于专栏:butterfly100butterfly100

Chris Richardson 微服务系列翻译全7篇链接:

  • 微服务介绍
  • 构建微服务之使用API网关(本文)
  • 构建微服务之微服务架构的进程通讯
  • 微服务架构中的服务发现
  • 微服务之事件驱动的数据管理
  • 微服务部署
  • 重构单体应用为微服务

原文链接:Building Microservices: Using an API Gateway


介绍

假设我们为一个商品应用开发一个移动APP,我们应该提供一个产品详情页来展示指定产品的信息。Amazon Android 应用在商品详情页展示的内容,如下图所示:

尽管只是移动APP,商品详情页依然展示给我们很多信息,不仅包括基本信息(名称、描述、价格),还包含如下内容:

  • 购物车中的商品数
  • 历史订单记录
  • 买家评价
  • 低库存预警
  • 送货选项
  • 推荐:包括与此商品一起购买的其他商品、购买该商品的顾客还买的其他商品、购买该商品的顾客还看过其他的商品
  • 其他购物选项

使用单体应用架构时,移动APP通过单一的 REST 请求(GET api.company.com/productdetails/productId)来获取展示的数据。负载均衡会将请求路由到多个相同实例的其中一个,然后程序查询各种数据库表,返回数据给客户端。

对应如果采用微服务架构,展示在产品详情页的数据会来自不同的微服务上。下面列举一些微服务对应的展示数据:

  • 购物车服务:购物车中的商品数
  • 订单服务:订单记录
  • 目录服务:商品基本信息,如名称、图片和价格
  • 评论服务:用户评价
  • 库存服务:低库存预警
  • 配送服务:送货选项、期限和费用
  • 推荐服务:推荐商品

客户端如何访问这些服务,让我们看看下面的方法。

客户端与服务端直接通信

理论上客户端可以直接请求每个微服务,每个微服务都有一个公开的节点(https://serviceName.api.company.com),该 URL 映射到负载均衡,然后被分发到可用的实例上处理,为了获取产品详情,移动客户端需要向上述每个服务发送请求。

遗憾的是,这种方法存在挑战和局限:

1)客户端需求和每个微服务暴露出的细粒度 API 不匹配。本例中客户端需要发送7个不同的请求,在一个复杂的应用中请求数甚至还要更多,例如亚马逊在显示他们的产品页面时会调用数百个服务。这种方法还使得客户端代码非常复杂。

2)一些服务使用的协议对 web 并不友好。一个服务可能使用 Thrift 的二进制 RPC,而另一个服务可能使用 AMQP 消息协议。这些协议不是浏览器和防火墙友好的,最好在内部使用。而防火墙之外,应用程序最好使用 HTTP 或 WebSocket 之类的协议。

3)这种方法会使得微服务难以重构。随着时间的推移,我们可能要重新规划、合并或拆分微服务,如果客户端直接与微服务通信的话,对这些微服务进行重构变得异常困难。

正是这些原因,采用客户端直接调用微服务的方式并不明智。

使用 API 网关

通常更好的方式是使用 API 网关,API 网关是提供系统唯一入口的服务器,他和设计模式中的 外观模式 类似:API 网关封装内部系统架构,并向客户端提供 API。它还可能负责诸如 用户验证、监控、负载均衡、缓存、请求管理、静态响应处理等功能。下图展示了适应 API 网关的架构:

API 网关负责请求路由、组合和协议转换。来自客户端的所有请求都先经过 API 网关,然后被路由到对应的微服务中,API 网关通常调用多个微服务并聚合其结果来处理请求。它可以在 web 协议(如 HTTP 和 WebSocket)与内部使用的非 web 协议之间转换。

API 网关可以为每个客户端提供定制的 API,它通常为移动客户端暴露粗粒度的 API。例如:商品详情页,API 网关提供 (/productdetails?productid=xxx) 节点使得移动客户端单一请求可以获取所有的产品明细。API 网关调用各个服务(商品信息、推荐、评论等)合并结果并返回。

Netflix API网关 就是一个很好的 API 网关实例。Netflix 流媒体服务提供给成百上千的设备使用,包括电视、机顶盒、智能手机、游戏系统、平板电脑等。最初,Netflix 视图为他们的流服务提供通用的 API,然而,他们发现由于设备的独特需求,这种设计方式不能很好的工作。如今他们使用 API 网关通过运行设备的适配器代码为客户端提供定制的 API,通常适配器为每个请求平均调用6~7个微服务,Netflix API网关每天处理数十亿请求。

使用 API 网关的优势及劣势

使用 API 网关有优势也有不足。

最大优点是: 1)它封装了应用的内部结构,客户端只需要简单的与 API 网关交互即可,而不用直接调用每个服务。 2)API 网关为不同的客户端提供定制的 API,减少了客户端和应用间的交互次数,并大大简化了客户端的代码。

API 网关也有其不足: 1)它本身增加了一个需要开发、部署和维护的高可用组件。 2)API 网关有时候变成了开发的瓶颈。开发者为了暴露新的微服务必须更新 API 网关。API 网关的更新流程要尽可能的简单,否则,开发人员不得不排队等待。尽管它有这些不足,但对于大部分的应用程序而言,使用 API 网关是合理的。

实现一个 API 网关

目前我们讨论了 API 网关的动机和一些优缺点。下面我们看一些需要考虑的一些设计问题。

性能与扩展性

只有少数公司拥有 Netflix 这样的规模,每天需要处理数十亿的请求。对于大多数程序而言,API 网关的性能和可扩展性是非常重要的。因此,API 网关构建在一个支持异步、IO 非阻塞的平台上是合理的。有多种不同的技术可参考:JVM 上,基于 NIO 的框架,比如 Netty、Vertx、 Spring Reactor 或 JBoss Undertow 等。一个流行的选项是 Node.js,他是构建于 Chrome JS 引擎的平台。另一个选项是 NGINX Plus,他提供了成熟、可扩展、高性能的 web 服务器和一个易于部署的、可配置可编程的反向代理。NGINX Plus 可以管理身份验证、权限控制、负载均衡、缓存以及应用级别的健康检查及监控。

使用响应式编程模型

API 网关将请求路由到相应的多个微服务并合并处理结果,对于一些请求,例如产品详情页,后端对应的服务是彼此独立的,为了减少响应时间,API 网关应并行处理这些请求。然而有时候,请求之间是有依赖关系的,在请求微服务之前,API 网关需要调用身份验证服务来验证请求的合法性。类似的,获取用户心愿单上的产品信息时,API 网关需要先获取包含这些信息的客户资料,然后再去获取信息的详情。另一个有趣的例子就是:Netflix Video Grid

使用传统的异步回调方式来写 API 组合代码会把你带入地狱。代码会变的混乱、难以理解且容易出错。更好的方式是使用响应式方法,以一种声明式样式编写 API 网关代码。例如:Scala中的 Future 、Java 8中的 CompletableFuture 以及JavaScript中的 Promise,还有微软为.NET开发的 Reactive Extensions。Netflix 为他们的 API 网关创建了 RxJava for JVM,此外还有 RxJS for JavaScript,既可以在浏览器中运行,也可以在Node.js 中运行。响应式风格将帮助你写出简洁高效的 API 网关代码。

服务调用

微服务架构是一个进程间通信的分布式系统, 有两种进程间通信方式:一种是采用异步、基于消息传递的机制。例如:JMS 或 AMQP 这样的消息组件;另一种是使用 HTTP 或 Thrfit 这种同步机制进行通信。通常,一个系统会同时使用同步和异步方式,甚至还会使用同一类型的多种实现。总之,API 网关需要支持不同的通信机制。

服务发现

API 网关需要知道和他通信的每个微服务的地址(IP和端口号)。传统应用中,可以使用硬编码的方式,但是在现代基于云的微服务应用中,这不是一个容易解决的问题。基础架构服务(例如:消息组件)通常会有一个静态地址,可以在环境变量中指定。然而,获取一个微服务地址就不是简单的事了,微服务的地址是动态分配的,一组服务实例可能因为自动扩展或升级而动态的变化。因此 API 网关需要服务发现机制,可以是服务器端发现,或者是客户端发现(后面的文章会详细介绍服务发现的问题)。如果使用客户端发现的话,API 网关应该能查询服务注册中心,这是一个包含所有微服务实例及其地址的数据库。

处理局部故障

局部故障在分布式系统中很常见,当一个服务调用另一个服务,当后者响应慢或不可用时就出现了这个问题。API 网关不能因为无限期的等待下游服务而阻塞。不过,如何处理失败取决于应用场景或具体哪个服务失败,例如:产品详情页,推荐服务挂了,那么 API 网关应该返回其他产品信息,保障产品对用户仍然可用,推荐内容可为空或使用固定的 Top 10 列表取代。不过,如果产品服务挂了,那么 API 网关应该返回客户端错误信息。

API 网关也可以缓存返回的数据。例如:产品价格变动不频繁,当价格服务不可用时,API 网关可以返回缓存的价格数据。数据可以是 API 网关自己缓存,也可以使用 Redis 或 Memcached之类的外部缓存。通过返回默认值或缓存值,API 网关保证局部故障不会影响用户体验。

Netflix Hystrix 在编写代码调用远程服务时是非常有用的,Hystrix 会标记超过特定阀值的调用为超时,他还实现了『熔断器』模式来防止对无响应服务的更多请求,如果一个服务的出错率超过了特定阀值,那么 Hystrix 会触发熔断器,所有请求会快速失败并持续一段时间。Hystrix 允许用户定义请求失败时的 fallback 操作,例如:读取缓存或返回默认值。如果你在使用 JVM ,那么应该考虑使用 Hystrix,如果使用的是非 JVM 环境,那么可以使用一个功能相同的库。

总结

对于大部分基于微服务的应用,实现 API 网关作为应用的单一入口是明智的。API 网关负责请求路由、聚合、协议转换。为每个客户端提供特定的 API,还可以通过返回默认值或缓存值来处理后端服务的调用失败。下篇文章,我们将讨论服务间的通信。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-11-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 客户端与服务端直接通信
  • 使用 API 网关
  • 使用 API 网关的优势及劣势
  • 实现一个 API 网关
    • 性能与扩展性
      • 使用响应式编程模型
        • 服务调用
          • 服务发现
            • 处理局部故障
            • 总结
            相关产品与服务
            API 网关
            腾讯云 API 网关(API Gateway)是腾讯云推出的一种 API 托管服务,能提供 API 的完整生命周期管理,包括创建、维护、发布、运行、下线等。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档