您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
微服务:从设计到部署(一)
 
来源:网络 发布于: 2017-10-9
  2332  次浏览      16
 

1、微服务简介

如今微服务倍受关注:文章、博客、社交媒体讨论和会议演讲。微服务的走向正在迅速朝向加德纳技术成熟度曲线(Gartner Hype cycle)的高峰。与此同时,也有持怀疑态度的软件社区人员认为微服务没什么新鲜可言。反对者声称它的思想只是面向服务架构(SOA)的重塑。然而,无论是炒作还是怀疑,不可否认微服务架构模式具有非常明显的优势——特别是在实施敏捷开发和复杂的企业应用交付方面。

本书的七个章主要介绍如何设计、构建和部署微服务,这是本书的第一章。在此章节中,您将了解微服务的由来和与传统单体应用模式的对比。这本电子书描述了许多关于微服务架构方面的内容。无论是项目意义还是实施方面,您都将了解到微服务架构模式的优点和缺点。

我们先来看看为什么要考虑使用微服务。

1.1、构建单体应用

我们想一下,您开始开发一个打车应用,打算与 Uber 和 Hailo 竞争。经过初步交流和需求收集,您将手动或者使用类似 Rails、Spring Boot、Play 或者 Maven 等平台来生成一个新项目。

该新应用是一个模块化的六边形架构,如图 1-1 所示:

图 1-1、一个简单的打车应用

该应用的核心是由模块实现的业务逻辑,它定义了服务、领域对象和事件。围绕核心的是与外部世界接口对接的适配器。适配器示例包括数据库访问组件、生产和消费消息的消息组件和暴露了 API 或实现了一个 UI 的 web 组件。

尽管有一个逻辑模块化的架构,但应用程序被作为一个单体进行打包和部署。实际格式取决于应用程序的语言和框架。例如,许多 Java 应用程序被打包成 WAR 文件部署在如 Tomcat 或者 Jetty 之类的应用服务器上。其他 Java 应用程序被打包成自包含(self-contained)的可执行 JAR。类似地,Rails 和 Node.js 应用程序被打包为有目录层次的结构。

以这种风格编写的应用是很常见的。他们很容易开发,因为我们的 IDE 和其他工具就是专注于构建单体应用。这些应用程序也很容易测试。您可以通过简单地启动并使用如 Selenium 测试包来测试 UI 以轻松地实现端到端(end-to-end)测试。单体应用同样易于部署。你只需拷贝打包好的应用程序到服务器。您还可以通过运行多个副本和结合负载均衡器来扩展应用。在项目的早期阶段,它可以良好运作。

1.2、走向单体地狱

不幸的是,这种简单的方法有很大的局限性。成功的应用有一个趋势,随着时间推移而变得越来越臃肿。您的开发团队在每个冲刺阶段都要实现了更多的用户需求,这意味着需要添加了许多行代码。几年之后,您的小而简单的应用将会逐渐成长为庞然大物似的单体。为了给出一个极端的示例,我最近和一位开发者做了交谈,他正在编写一个工具用于从他们的数百万行代码(lines of code,LOC)应用中分析出数千个 JAR 之间的依赖。我相信这是大量开发者在多年齐心协力下创造了这样的野兽。

一旦您的应用程序成为了一个庞大、复杂的单体,您的开发组织可能陷入了一个痛苦的世界。敏捷开发和交付的任何一次尝试都将原地徘徊。一个主要问题是应用程序实在是非常复杂。对于任何一个开发人员来说,这实在太大了,这是可以理解。最终,正确地修复 bug 和实现新功能变得非常困难而耗时。此外,这个趋势就像是往下的螺旋。如果基本代码都难以理解,那么改变也不会变得正确,您最终得到的将是一个巨大且不可思议的大泥球。

应用程序的规模也将减缓发展。应用程序越大,启动的时间越长。我调查过开发者们的单体应用的大小和性能,一些报告的启动时间为 12 分钟。我也听说过应用程序启动需要 40 分钟以上的怪事。如果开发人员经常要重启应用服务器,那么很大一部分时间都是在等待中度过,他们的生产力将受到限制。

另一个大问题是,复杂的单体应用本身就是持续部署的障碍。如今,SaaS 应用发展到了每天可多次将变更推送到生产环境中。这对于复杂的单体非常困难,因为您需要重新部署整个应用程序才能更新其中任何一部分。对于我之前提到的漫长启动时间,这也不会是什么好事。此外,因为变化所产生的影响通常不是很明确,您很可能需要做大量的手工测试。因此,持续部署是不可能做到的。

当不同模块存在资源需求冲突时,单体应用可能难以扩展。例如,一个模块可能会执行 CPU 密集型图像处理逻辑,理想情况下是部署在 Amazon EC2 Compute Optimized 实例中。另一个模块可能是内存数据库,最适合部署到 EC2 Memory-optimized 实例。然而,因为这些模块被部署在一起,您必须在硬件选择上做出妥协。

单体应用的另一个问题是可靠性。因为所有模块运行在同一进程。任何模块的一个 bug,比如内存泄漏,可能会拖垮整个进程。此外,由于应用程序的所有实例都是相同的,该错误将影响到整个应用的可用性。

最后但同样重要,单体应用使得采用新框架和语言变得非常困难。例如,我们假设您有 200 万行代码使用了 XYZ 框架编写。使用较新的 ABC 框架来重写整个应用,这将是非常昂贵的(在时间和成本方面),即使框架非常好。因此,这对于采用新技术是一个非常大的障碍。您在项目开始时无论选择何种新技术都将会感到困扰。

总结一下:您有一个成功的关键业务应用程序,它已经发展成为一个只有少数开发人员(如果有的话)能够理解的巨大单体。它使用了过时、非生产性技术编写的,这使得招聘优秀开发人员变得困难。应用程序难以扩展,不可靠。因此敏捷开发和应用交付是不可能的。

那么您能做些什么呢?

1.3、微服务-解决复杂问题

许多组织,如 Amazon、eBay 和 Netflix,已经采用现在所谓的微服务架构模式解决了这个问题,而不是构建一个臃肿的单体应用。它的思路是将您的应用程序分解成一套较小的互连服务。

一个服务通常实现了一组不同的特性或者功能,例如订单管理、客户管理等。每一个微服务都是一个迷你应用,它自己的六边形架构包括业务逻辑以及多个适配器。

一些微服务会暴露一个供其他微服务或应用客户端消费的 API。其他微服务可能实现了一个 web UI。在运行时,每个实例通常是一个云虚拟机(virtual machine,VM)或者一个 Docker 容器。

例如,前面描述的系统可能分解成如图 1-2 所示:

图 1-2、一个单体应用分解成微服务

应用程序的每个功能区域现在都由自己的微服务实现。此外,Web 应用程序被分为一组更简单的 Web 应用程序。例如,以我们的出租车为例,一个专门是乘客的,一个专门是司机的。这使得它更容易地为特定的用户、司机、设备或者专门的用例部署不同的场景。每个后端服务暴露一个 REST API,大部分的服务消费由其他服务提供的 API。例如,司机管理使用了通知服务器来告知一个可用司机关于一个潜在路程。UI 服务调用了其他服务来渲染页面。服务也可以使用异步、基于消息的通信。本电子书后面将会详细介绍服务间的通信。

一些 REST API 也暴露给移动端应用供司机和乘客使用。然而,应用不能直接访问后端服务。相反,他们之间的通信是由一个称为 API 网关(API Gateway)的中介负责。API 网关负责负载均衡、缓存、访问控制、API计量和监控,可以通过使用 NGINX 来实现。第 2 章详细讨论 API 网关。

图 1-3、开发和交付中的缩放立方(Scale Cube)

微服务架构模式相当于此缩放立方的 Y 轴坐标,此立方是一个来自《架构即未来》的三维伸缩模型。另外两个坐标轴是由运行多个相同应用程序副本的负载均衡器组成的 X 轴缩放和 Z 轴坐标(或者数据分区),其中请求的属性(例如,一行记录的主键或者客户标识)用于将请求路由到特定的服务器。

应用程序通常将这三种类型的坐标方式一起使用。Y 轴坐标将应用分解成微服务,如图 1-2 所示。

在运行时,X 坐标轴上运行着服务的多个实例,每一个服务配合负载均衡器以满足吞吐量和可用性。某些应用程序也有可能使用 Z 坐标轴来进行分区服务。图 1-4 展示了如何用 Docker 将旅途管理(Trip Management)服务部署到 Amazon EC2 上运行。

图 1-4、使用 Docker 部署旅途管理服务

在运行时,旅途管理服务由多个服务实例组成,每个服务实例是一个 Docker 容器。为了实现高可用,容器是在多个云虚拟机上运行的。服务实例的前方是一个如 NGINX 的负载均衡器,用于跨实例分发请求。负载均衡器也可以处理其他问题,如缓存、访问控制、API 度量和监控。

微服务架构模式明显影响到了应用程序与数据库之间的关系。与与其他共享单个数据库模式(schema)服务不同,每一个服务都有自己的数据库模式。一方面,这种做法是与企业级数据库数据模型的想法不符,此外,它经常导致一些数据冗余。然而,如果您想从微服务中受益,每一个服务都应该有自己的数据库模式。因为它做到了松耦合。图 1-5 展示了数据库架构示例应用程序。

每个服务都有自己的数据库。而且,服务可以使用一种最适合其需求、号称多语言持久架构(polyglot persistence architecture)的数据库。例如,司机管理,找到与潜在乘客接近的司机必须使用支持高效地理查询的数据库。

图 1-5、打车应用的数据库架构

从表面上看,微服务架构模式类似于 SOA。微服务是由一组服务组成。然而,换另一种方式去思考微服务架构模式,它是没有商业化的 SOA,没有集成 Web 服务规范(WS-*)和企业服务总线(Enterprise Service Bus,ESB)。基于微服务的应用支持更简单、轻量级的协议,例如,REST,而不是 WS-*。他们也尽量避免使用 ESB,而是实现微服务本身具有类似 ESB 的功能。微服务架构也拒绝了 SOA 的其他部分,例如,数据访问规范模式概念。

1.4、微服务的优点

微服务架构模式有许多非常好的地方。第一,它解决了复杂问题。它把可能会变得庞大的单体应用程序分解成一套服务。虽然功能数量不变,但是应用程序已经被分解成可管理的块或者服务。每个服务都有一个以远程过程调用(RPC)驱动或者消息驱动的 API 明确定义的边界。微服务架构模式强制一定程度的模块化,实际上,使用单体基础代码来实现是极其困难的。因此,个体服务能被更快地开发,并更容易理解与维护。

第二,这种架构使得每个服务都可以由一个团队独立专注开发。开发者可以自由选择任何符合服务 API 契约的技术。当然,更多的组织是希望通过技术选型限制来避免完全混乱的状态。然而,这种自由意味着开发人员不再有可能在这种自由的新项目开始时使用过时的技术。当编写一个新服务时,他们可以选择当前的技术。此外,由于服务比较小,使用当前技术重写旧服务将变得更加可行。

第三,微服务架构模式可以实现每一个微服务独立部署。开发人员根本不需要去协调部署本地变更到它们的服务。这些变更一经测试即可立即部署。比如,UI 团队可以执行 A|B 测试,并快速迭代 UI 变更。微服务架构模式使得持续部署成为可能。

最后,微服务架构模式使得每个服务能够独立扩展。您可以仅部署满足每个服务的容量和可用性约束的实例数目。此外,您可以使用与服务资源要求最匹配的硬件。例如,您可以在 EC2 Compute Optimized 实例上部署一个 CPU 密集型图像处理服务,并且在 EC2 Memory-optimized 实例上部署一个内存数据库服务。

1.5、微服务的缺点

就像 Fred Brooks 近 30 年前写的《人月神话》说的,没有银弹。像其他技术一样,微服务架构模式也是如此,存在着缺点。其中一个缺点就是名称本身。微服务这个术语的重点过多偏向于服务的规模。事实上,有些开发者主张构建极细粒度的 10-100 LOC(代码行) 服务虽然小型服务可能比较好,但重要的是要记住,小型服务只是一种手段,而不是主要目标。微服务的目标在于充分分解应用程序以方便应用敏捷开发和部署。

微服务另一个主要的缺点是由于微服务是一个分布式系统而变得复杂。开发者需要选择和实现基于消息或者 RPC 的进程间通信机制。此外,由于目标请求可能很慢或者不可用,他们还必须编写代码来处理局部故障。虽然这些都不是很复杂高深的事,但模块间通过语言级方法/过程调用相互调用,这比单体应用要复杂得多。

微服务的另一个挑战是分区数据库架构。更多多个业务实体的业务事务是相当普遍的。这些事务在单体应用中的实现显得微不足道,因为只有一个单独的数据库。在基于微服务的应用程序中,您需要更新不同服务所有用的数据库。通常不会选择分布式事务,不仅仅是因为 CAP 定理。他们根本不支持如今高度可扩展的 NoSQL 数据库和消息代理。您最后不得不使用最终基于一致性的方法,这对于开发人员来说更具挑战性。

测试微服务应用程序也很复杂。例如,使用现代的框架如 Sprig Boot,只需要编写一个测试类来启动一个单体 web 应用程序并测试其 REST API。相比之下,一个类似的测试类对于微服务来说需要启动该服务及其所依赖的任何服务,或者至少为这些服务配置存根。再次声明,虽然这不是一件高深的事情,但不要低估了这样做的复杂性。

微服务架构模式的另一个主要的挑战是实现了跨越多服务变更。例如,我们假设您正在实现一个变更服务 A、B 和 C 的需求,其中 A 依赖于 B,并且 B 依赖于 C。在单体应用程序中,您可以简单地修改相应的模块、整合变更并一次性部署他们。相反,在微服务中您需要仔细规划和协调出现的变更到每一个服务。例如,您需要更新服务 C,然后更新服务 B,最后更新服务 A。幸运的是,大多数变更只会影响一个服务;需要协调的多服务变更相对较少。

部署基于微服务的应用程序也是非常地复杂。一个单体应用可以很容易地部署到基于传统负载均衡器的一组相同的服务器上。每个应用程序实例都配置有基础设施服务的位置(主机和端口),比如数据库和消息代理。相比之下,微服务应用程序通常由大量的服务组成。例如,据 Adrian Cockcroft,Hailo 拥有 160 个不同的服务,Netflix 拥有超过 600 个服务。

每个服务都有多个运行时实例。还有更多的移动部件需要配置、部署、扩展和监控。此外,您还需要实现服务发现机制,使得服务能够发现需要与之通信的任何其他服务的位置(主机和端口)。传统比较麻烦的基于票据(ticket-based)和手动操作方式无法扩展到如此复杂程度。因此,成功部署微服务应用程序要求开发人员能高度控制部署方式和高度自动化。

一种自动化的方式是使用现成的平台即服务(PaaS),如 Cloud Foundry。PaaS 为开发人员提供了一种简单的方式来部署和管理他们的微服务。它让开发人员避开了诸如采购和配置 IT 资源等烦恼。同时,配置 PaaS 的系统与网络专业人员可以确保最佳实践和落实公司策略。

自动化微服务部署的另一个方式是开发自己的 PaaS。一个普遍的起点是使用集群方案,如 Kubernetes,与 Docker 等容器技术相结合。在本书最后我们将看到基于软件的应用交付方式如 NGINX 是如何在微服务级别处理缓存、访问控制、API 计量和监控,可以帮助解决这个问题。

1.6、总结

构建复杂的微服务应用程序本质上是困难的。单体架构模式只适用于简单、轻量级的应用程序,如果您使用它来构建复杂应用,您最终会陷入一个痛苦的世界。微服务架构模式是复杂、持续发展应用的一个更好的选择。尽管它存在着缺点和实现挑战。

在后面的章节中,我将介绍微服务架构的方方面面并探讨诸如服务发现、服务部署方案以及将单体应用重构为服务的策略。

微服务实战:NGINX Plus 作为反向代理服务器

By Floyd Smith

10000 个网站中有超过 50% 使用 NGINX,这主要是因为它具有作为反向代理服务器的能力。您可以把 NGINX 放在当前应用程序甚至是数据库服务器之前以获取各种功能 —— 更高的性能、更高的安全性、可扩展性、灵活性等。你现有的应用程序只需要配置代码和作出很少或无需改变。对于存在性能压力的站点,或者预计未来存在高负荷,效果看起来似乎没那么神奇。

那么这与微服务有什么关系呢?实现一个反向代理服务器,并使用 NGINX 的其他功能来为您提供架构灵活性。反向代理服务器、静态和应用文件缓存、SSL/TLS 和 HTTP/2 都会从您的应用程序剔除。让应用程序只做它该做的事,NGINX 还可作为负载均衡器,微服务实施过程中的一个关键角色。先进的 NGINX Plus 的功能包含了复杂的负载均衡算法、多种方式的会话持久和管理监控,这些对微服务尤其有用(NGINX 最近还增加了使用 DNS SRV 记录的服务发现支持,这是一个顶尖的功能)。而且,如本章所述,NGINX 可以自动化部署微服务。

此外,NGINX 还提供了必要的功能来支撑 NGINX 微服务参考架构中的三大模型。代理模型使用 NGINX 作为 API 网关;网格路由模型使用了一个额外的 NGINX 作为进程间通信中枢;Fabric 模型中每个微服务使用一个 NGINX 来控制 HTTP 流量,在微服务之间实现 SSL/TLS,这非常具有突破性。

2、使用 API 网关

本书的七个章节是关于设计、构建和部署微服务。第一章介绍了微服务架构模式。它阐述使用微服务的优点与缺点,以及尽管如此,微服务通常是复杂应用的理想选择。该系列的第二篇文章将探讨使用 API 网关构建微服务。

当您选择将应用程序构建成为一组微服务时,您需要决定应用程序客户端将如何与微服务进行交互。单体应用程序只有一组端点(endpoint),通常使用复制(replicated)结合负载均衡来分配流量。

然而,在微服务架构中,每个微服务都暴露一组通常比较细颗粒的端点。在本文中,我们将研究如何改进客户端通信,并提出一个使用 API 网关的方案。

2.1、简介

我们假设您正在为一个购物应用开发一个本地原生移动客户端。您可能需要实现一个产品详细信息页面,用于展示给定商品的信息。

例如,图 2-1 展示了在 Amazon 的 Android 移动应用中的滚动产品信息时所看的内容。

图 2-1、一个简单的购物应用

即使这是一个智能手机应用,产品详细信息页面展示了很多信息。例如,不仅有基本的产品信息,如名称、描述和价格,页面还展示了:

购物车中的物品数量

订单历史

客户评论

低库存警告

配送选项

各种推荐,包括了买了此产品的客户经常买的其他产品

选择性购买选项

在使用单体应用架构的情况下,移动客户端通过对应用程序进行单个 REST 调用来检索此数据,例如:

GET api.company.com/productdetails/productId

负载均衡器将请求路由到几个相同应用程序实例中的其中一个。之后,应用程序查询各个数据库表并返回响应给客户端。相比之下,当使用微服务架构时,产品详细页面上展示的数据来自多个微服务。以下是一些可能拥有特定商品页面展示的数据的微服务:

订单服务 - 订单历史

目录(catalog)服务 - 基本的产品信息,如产品名称、图片和价格

评价服务 - 客户评价

库存服务 - 低库存警告

配送服务 - 配送选项、期限和费用,由配送方的 API 单独提供

推荐服务 - 推荐类目

图 2-2、将移动客户端的需求映射到相关的微服务

我们需要决定移动客户端如何访问这些服务。让我们来看看有哪些方式。

2.2、客户端与微服务直接通信

理论上,客户端可以直接向每个微服务发送请求。每个微服务都有一个公开的端点:

https://serviceName.api.company.name

该 URL 将映射到用于跨可用实例分发请求的微服务负载均衡器,要检索特定的产品页面信息,移动客户端将向上述的每个微服务发送请求。

不幸的是,这种方式存在着挑战与限制。第一个问题是客户端的需求与每个微服务暴露的细粒度的 API 不匹配。此示例中,客户端需要进行七次单独请求。如果在更加复杂的应用中,它可能需要做更多的工作。例如,Amazon 展示了在产品页面渲染中如何牵涉到数百个微服务。虽然客户端可以通过 LAN 发送许多请求,但在公共互联网下效率低下,在移动网络必然是不切实际。

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

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

由于存在这些问题,很少有客户端直接与微服务进行通信。

2.3、使用 API 网关

通常更好的方法是使用 API 网关。一个 API 网关是一个服务器,是系统的单入口点。它类似于面向对象设计模式中的门面(Facade)模式。API 网关封装了内部系统架构,并针对每个客户端提供一个定制的 API。它还可用于认证、监控、负载均衡、缓存和静态响应处理。

图 2-3 展示了 API 通常如何整合架构

使用 API 网关的微服务

API 网关负责请求路由、组合和协议转换。所有的客户端请求首先通过 API 网关,之后请求被路由到适当的服务。API 网关通常会通过调用多个微服务和聚合结果来处理一个请求。它可以在 Web 协议(如 HTTP 和 WebSocket)和用于内部的非 Web 友好协议之间进行转换。

API 还可以为每个客户端提供一个定制的 API。它通常会为移动客户端暴露一个粗粒度的 API。例如,考虑一下产品详细信息场景。API 网关可以提供一个端点 /productdetails?productid=xxx,如图 2-3 所示,一个使用了 API 网关的微服务。允许移动客户端通过一个单独的请求来检索所有产品详细信息。API 网关通过调用各种服务(产品信息、推荐、评价等)并组合结果。

API 网关的一个很好的案例是 Netflix API 网关。Netflix 流媒体服务可用于数百种不同类型的设备,包括电视机、机顶盒、智能手机、游戏机和平板电脑等。起初,Netflix 尝试为他们的流媒体服务提供一个通用的 API。但是,他们发现由于设备种类繁多,并且他们各自有着不同需求,所以并不是能很好地运作。如今,他们使用了 API 网关,通过运行特定设备适配代码来为每个设备提供一个定制 API。

2.4、API 网关的优点和缺点

正如您所料,使用 API 网关同样存在好处与坏处。使用 API 网关的主要好处是它封装了应用程序的内部结构。客户端只需要与网关通信,而不必调用特定的服务。API 网关为每种类型的客户端提供了特定的 API,减少了客户端与应用程序之间的往返次数。它还简化了客户端代码。

API 网关也存在一些缺点,它是另一个高度可用的组件,需要开发、部署和管理。还有另一个风险是 API 网关可能会成为开发瓶颈。开发人员必须更新 API 网关以暴露每个微服务的端点。

重要的是更新 API 网关的过程应尽可能地轻一些。否则,开发人员将被迫排队等待网关更新。尽管 API 网关存在这些缺点,但对于大多数的真实应用来说,使用 API 是合理的。

2.5、实施 API 网关

我们已经了解了使用 API 网关的动机与权衡。接下来让我们看看您需要考虑的各种设计问题。

2.5.1、性能与可扩展性

只有少数公司能达到 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 可以管理身份验证、访问控制、负载均衡请求、缓存响应,并且提供了应用程序健康检查和监控功能。

2.5.2、使用响应式编程模型

API 网关通过简单地把他们(请求)路由到适当的后端服务来处理一些请求。它通过调用多个后端服务并聚合结果来处理其他请求。对于某些请求,如产品详细信息请求,对后端服务请求而言是彼此独立的。为了缩短响应时间到最小,API 网关应该并发执行独立请求。

然而,有时候,请求是相互依赖的。首先,API 网关可能需要在将请求路由到后端服务之前,通过调用验证服务来验证请求。同样,为了从客户的愿望清单中获取关于产品的信息,API 网关首先必须检索包含该信息的客户资料,然后检索每个产品的信息。API 组合的另一个有趣的案例是 Netflix 视频网格。

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

2.5.3、服务调用

一个基于微服务的应用程序是一个分布式系统,必须使用一个进程间(inter-process)通信机制。有两种进程间通信方案。一是使用基于消息的异步机制。某些实现采用了消息代理,如 JMS 和 AMQP。其他采用无代理的方式直接与服务通信,如 Zeromq。

另一种类型的进程间通信采用了同步机制,如 HTTP 和 Thrift。系统通常会同时使用异步和同步方式。甚至可以为每种方式应用多个实现。因此,API 网关需要支持各种通信机制。

2.5.4、服务发现

API 网关需要知道与其通信的每个微服务的位置(IP 地址和端口)。传统应用程序中,您可以将这些位置硬编码,但在现代基于云的微服务应用程序中,找到所需的位置不是一个简单的问题。

基础设施服务(比如消息代理)通常都有一个可以通过系统环境变量来指定的静态位置。但是,要确定应用程序服务的位置并不是那么容易。

应用服务可以动态分配位置。此外,由于自动扩缩与升级,一个服务的整组实例可以动态变更。因此,API 网关与系统中的任何其他服务客户端一样,需要使用系统的服务发现机制:服务端发现或客户端发现。 第4章中更详细地描述了服务发现。现在需要注意的是,如果系统使用客户端发现,API 网关必须能够查询服务注册表,该注册表是所有微服务实例及其位置的数据库。

2.5.5、处理局部故障

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

如果可以,API 网关还可以返回缓存数据。例如,由于产品价格变化不大,如果价格服务不可用,API 网关可以返回被缓存的价格数据。数据可以由 API 网关缓存或存储在外部缓存中,如 Redis 或者 Memcached。API 网关通过返回默认数据或缓存数据,确保了系统发生故障时最小程度上影响到用户体验。

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

2.6、总结

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

微服务实战:NGINX Plus 作为 API 网关

by Floyd Smith

本章讨论了 API 网关如何作为系统的单入口点。它可以处理诸如负载均衡、缓存、监控和协议转换等其他功能 —— 当 NGINX 充当一个反向代理服务器时,可以作为系统的单入口点,并且支持所有提到的一个 API 网关具有的附加功能。因此使用 NGINX 作为 API 网关的主机可以很好地工作。

将 NGINX 作为 API 网关并不是本书最开始的想法。NGINX Plus 是用于管理和保护基于 HTTP 的 API 流量的领先平台。您可以实现自己的 API 网关或使用现有的 API 管理平台,其中许多使用了 NGINX。

使用 NGINX Plus 作为 API 网关的理由包括:

访问管理 - 上至典型的 Web 应用级别,下至每个个体微服务级别,您都可以使用各种访问控制列表(ACL)方法,并且可以轻松实现 SSL/TLS。

可管理性与弹性 - 您可以使用 NGINX 的动态重新配置 API、Lua 模块、Perl 来更新基于 NGINX Plus 的 API 服务器,也可以通过 Chef、Puppet、ZooKeeper 或 DNS 来改变。

与第三方工具集成 - NGINX Plus 已经可以与某些先进的工具集成在一起 ,如 3scale,Kong 和 MuleSoft 集成平台(仅列举在 NGINX 网站上提及的工具)。

NGINX Plus 被广泛用作 NGINX 微服务参考架构中的 API 网关。利用在这里收集的文章以及 MRA (微服务参考架构)来了解如何在您自己的应用程序中实现这一点。

   
2332 次浏览       16
相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践