关于后端:Netflix-零配置服务网格与按需集群发现

8次阅读

共计 5138 个字符,预计需要花费 13 分钟才能阅读完成。

本文翻译自在 David Vroom, James Mulcahy, Ling Yuan, Rob Gulewich 编写的 Netflix 博客 Zero Configuration Service Mesh with On-Demand Cluster Discovery。

Netflix 置信大家并不生疏,在 Spring Cloud 生态中就有 Netflix 全家桶。多年前,我也曾将基于 Netflix OSS 构建的微服务架构搬上了 Kubernetes 平台,并继续折腾好几年。

Spring Cloud Netflix 有着宏大的用户群以及用户场景,其提供了微服务治理的一整套解决方案:服务发现 Eureka、客户端负载平衡 Ribbon、断路器 Hystrix、微服务网格 Zuul。

有过雷同经验的小伙伴应该都会同感,这样一套微服务解决方案的架构,通过多年的演进也会让人痛苦不堪:复杂度越来越高、版本碎片化重大、多语言多框架的反对和性能无奈对立等等。这也是 Netflix 本人也不得不面对的问题,随后他们将眼光转向了服务网格,并寻求一个无缝迁徙的计划。

这篇文章中,他们给出了答案:Netflix 与社区单干,并自建管制立体与已有的服务发现体系兼容。这套实现下来可能并不容易,也未看到他们要将其开源的想法,然而至多能够给大家一个参考。

顺便预报一下本人正在打算的一篇,如何将微服务平滑迁徙到 Flomesh 服务网格平台。不止无缝兼容 Eureka,还有 HashiCorp Consul,将来还会兼容更多的服务发现计划。

以下是原文的翻译:


在这篇文章中,咱们将探讨 Netflix 服务网格(Service Mesh)实际的相干信息:历史背景、动机,以及咱们如何与 Kinvolk 和 Envoy 社区单干,在简单的微服务环境中推动服务网格落地的一个特色:按需集群发现(On-demand Cluster Discovery)。

Netflix 的 IPC 简史

Netflix 是晚期云计算的采纳者,特地是对于大规模的公司:咱们在 2008 年开始了迁徙,并且到 2010 年,Netflix 的流媒体齐全运行在 AWS 上。明天咱们领有丰盛的工具,包含开源和商业的,所有这些都是为云原生环境设计的。然而,在 2010 年,简直没有这样的工具存在:CNCF 直到 2015 年才成立!因为没有现成的解决方案,咱们须要本人构建它们。

对于服务间的过程间通信(IPC),咱们须要一个中间层负载均衡器通常提供的丰盛功能集。咱们还须要一种解决方案,来应答云环境的事实:一个高度动静的环境,其中节点一直上线和下线,服务须要疾速响应变动并隔离失败。为了进步可用性,咱们设计了能够独自产生故障的零碎组件,以防止单点故障。这些设计准则疏导咱们走向了客户端负载平衡,而 2012 年圣诞节的宕机 进一步动摇了这个决策。在云晚期,咱们构建了 Eureka 用于服务发现,以及 Ribbon(外部名为 NIWS)用于 IPC。Eureka 解决了服务如何发现与其通信的实例的问题,而 Ribbon 提供了负载平衡的客户端,以及许多其余的弹性个性。这两项技术,加上一系列其余的弹性和混沌工具,产生了微小的收益:咱们的可靠性因而失去了显著的改善。

Eureka 和 Ribbon 提供了一个简略而弱小的接口,让它们的应用变得容易。一个服务与另一个服务通信,须要晓得两件事:目标服务的名称,以及流量是否应该是平安的。Eureka 为此提供的形象是虚构 IP(VIPs)用于非平安通信,和平安 VIPs(SVIPs)用于平安通信。服务向 Eureka 发表一个 VIP 名和端口(例如:_myservice_,端口 _8080_),或一个 SVIP 名和端口(例如:_myservice-secure_,端口 8443),或同时应用两者。IPC 客户端针对该 VIP 或 SVIP 进行实例化,而 Eureka 客户端代码通过从 Eureka 服务器获取它们来解决该 VIP 到一组 IP 和端口对的转换。客户端还能够抉择启用像重试或熔断这样的 IPC 性能,或者应用一组正当的默认值。

在这种架构中,服务间通信不再通过负载均衡器的单点故障通道。但问题是,Eureka 当初成为了 VIP 注册主机真实性的新的繁多故障点。然而,如果 Eureka 宕机,服务依然能够相互通信,只管它们的主机信息随着 VIP 的高低线而逐步过期。在故障期间以降级但可用的状态运行依然是相比齐全进行流量的显著改良。

在这种架构中,服务与服务间的通信不再通过负载均衡器的繁多故障点。但问题是,Eureka 当初成为了 VIP 注册主机真实性的新的繁多故障点。然而,如果 Eureka 宕机,服务依然能够相互通信,只管它们的主机信息随着 VIP 的高低线而逐步过期。在故障期间以降级但可用的状态运行依然是相比齐全进行流量的显著改良。

为什么抉择网格?

上述架构在过来的十年里为咱们服务得很好,但随着业务需要的变动和行业标准的演变,咱们的 IPC 生态系统在很多方面都减少了更多的复杂性。首先,咱们减少了不同的 IPC 客户端的数量。咱们的外部 IPC 流量当初是纯 REST、GraphQL 和 gRPC 的混合。其次,咱们从只应用 Java 环境迁徙到了多语言环境:咱们当初也反对 node.js、Python 以及各种开源和现成的软件。第三,咱们持续为 IPC 客户端减少更多功能,如 自适应并发限度、断路器、对冲和故障注入已成为咱们工程师为使零碎更牢靠而采纳的规范工具。与十年前相比,咱们当初反对更多功能、更多语言、更多客户端。确保所有这些实现之间的性能一致性并确保它们都以雷同的形式运行是具备挑战性的:咱们心愿这些性能有一个繁多、通过充沛测试的实现,这样咱们能够在一个中央进行更改和修复谬误。

这就是服务网格的价值所在:咱们能够在一个实现中集中 IPC 性能,并使每种语言的客户端尽可能简略:它们只须要晓得如何与本地代理通话。Envoy 对咱们来说是代理的绝佳抉择:它是一个通过战斗考验的开源产品,曾经在行业中被宽泛应用,领有 许多要害的弹性性能,以及当咱们须要扩大其性能时的 良好的扩大点。可能 通过一个集中的管制立体配置代理 是一个杀手级的性能:这使咱们能够动静配置客户端负载平衡,就像它是一个集中的负载均衡器,但依然防止了服务到服务申请门路中的负载均衡器作为繁多的故障点。

转向服务网格

一旦认定咱们决定转向服务网格是正确的抉择,下一个问题便是:咱们应如何进行迁徙?咱们确定了一些迁徙的限度条件。首先:咱们心愿保留现有的接口。通过指定 VIP 名称加上平安服务的形象为咱们提供了良好服务,咱们不想毁坏向后兼容性。其次:咱们心愿自动化迁徙,并使其尽可能无缝。这两个限度意味着咱们须要反对 Envoy 中的 Discovery 形象,以便 IPC 客户端能够持续在底层应用它。侥幸的是,Envoy 曾经有了 现成的形象 能够用。VIP 能够示意为 Envoy 集群,代理能够从咱们的管制立体应用集群发现服务 (CDS) 获取它们。这些集群中的主机示意为 Envoy 端点,能够应用端点发现服务 (EDS) 获取。

咱们很快遇到了一个无缝迁徙的阻碍:Envoy 要求在代理的配置中指定集群。如果服务 A 须要与集群 B 和 C 通信,那么须要在 A 的代理配置中定义集群 B 和 C。这在规模上可能具备挑战性:任何给定的服务可能会与数十个集群通信,而每个应用程序的集群汇合都是不同的。此外,Netflix 始终在变动:咱们一直推出新的我的项目,如直播、广告 和游戏,并且一直倒退咱们的架构。这意味着服务通信的集群会随着工夫的推移而扭转。鉴于咱们可用的 Envoy 原语,咱们评估了一些填充集群配置的不同办法:

  1. 让服务所有者定义他们的服务须要与之通信的集群。这个选项看似简略,但实际上,服务所有者并不总是晓得,或想要晓得,他们与哪些服务通信。服务通常会导入由其余团队提供的库,这些库在底层与多个其余服务通信,或与像遥测和日志记录等其余操作服务通信。这意味着服务所有者须要晓得这些辅助服务和库是如何在底层实现的,并在它们发生变化时调整配置。
  2. 依据服务的调用图主动生成 Envoy 配置。这种办法对于事后存在的服务来说很简略,然而在启动新服务或增加新的上游集群以进行通信时具备挑战性。
  3. 将所有集群推送到每个应用程序:这个选项以其简略性吸引了咱们,然而纸巾上的简略计算很快向咱们显示,将数百万个端点推送到每个代理是不可行的。

思考到咱们无缝驳回的指标,每个选项都有足够重大的毛病,使咱们摸索了另一个选项:如果咱们能在运行时按需获取集群信息,而不是事后定义它,会怎么?过后,服务网格工作仍在启动阶段,只有少数几个工程师在致力于它。咱们分割了 Kinvolk,看看他们是否能与咱们和 Envoy 社区单干施行这个性能。这次单干的后果是 按需集群发现 (On-Demand Cluster Discovery,ODCDS)。有了这个性能,代理当初能够在第一次尝试连贯它时查找集群信息,而不是在配置中事后定义所有集群。

有了这个性能,咱们须要给代理提供集群信息以供查问。咱们曾经开发了一个实现 Envoy XDS 服务的服务网格管制立体。而后咱们须要从 Eureka 获取服务信息以返回给代理。咱们将 Eureka 的 VIP 和 SVIP 示意为独自的 Envoy Cluster Discovery Service (CDS) 集群(因而,服务 myservice 可能有集群 myservice.vip 和 _myservice.svip_)。集群中的单个主机被示意为独自的 Endpoint Discovery Service (EDS) 端点。这使得咱们可能重复使用雷同的 Eureka 形象,并且像 Ribbon 这样的 IPC 客户端能够通过最小的更改转移到网格。管制立体和数据立体的更改到位后,流程如下所示:

  1. 客户端申请进入 Envoy。
  2. 依据 Host / :authority 头(此处应用的头可配置,但这是咱们的办法)提取指标集群。如果已知该集群,跳到步骤 7。
  3. 集群不存在,所以咱们暂停了正在传输的申请。
  4. 向管制立体的 Cluster Discovery Service (CDS) 端点发出请求。管制立体依据服务的配置和 Eureka 注册信息生成定制的 CDS 响应。
  5. Envoy 获取集群(CDS),触发通过 Endpoint Discovery Service (EDS) 拉取端点。依据该 VIP 或 SVIP 的 Eureka 状态信息返回集群的端点。
  6. 客户端申请解除暂停。
  7. Envoy 失常解决申请:它应用负载平衡算法抉择一个端点并发出请求。

这个流程在几毫秒内实现,但只在对集群的第一次申请时。之后,Envoy 的行为就如同集群是在配置中定义的一样。要害是,该零碎容许咱们无需任何配置即可无缝迁徙服务至服务网格,满足咱们的次要驳回限度之一。咱们出现的形象持续是 VIP 名称加上平安,并且咱们能够通过配置单个 IPC 客户端连贯到本地代理而不是间接连贯到上游应用程序来迁徙到网格。咱们持续应用 Eureka 作为 VIP 和实例状态的实在起源,这使得咱们可能在迁徙时反对一些应用程序在网格上,而另一些不在网格上的异构环境。还有一个额定的益处:咱们能够通过仅为咱们理论通信的集群获取数据来放弃 Envoy 的内存使用率较低。

上图展现了一个 Java 利用中的 IPC 客户端通过 Envoy 与注册为 SVIP A 的主机通信。Envoy 从网格管制立体获取 SVIP A 的集群和端点信息。网格管制立体从 Eureka 获取主机信息。

按需获取此数据的毛病是:这会减少对集群的第一次申请的提早。咱们遇到了服务在第一次申请时须要非常低提早拜访的用例,并且减少了几毫秒额定的开销。对于这些用例,服务须要预约义它们通信的集群,或在第一次申请之前筹备好连贯。咱们还思考过依据历史申请模式在代理启动时从管制立体预推送集群。总的来说,咱们感觉零碎中的升高的复杂性证实了对大量服务的毛病是正当的。

咱们在服务网格之旅的初期。当初咱们真诚地应用它,咱们心愿与社区单干做出更多的 Envoy 改良。将咱们的 自适应并发限度 实现移植到 Envoy 是一个很好的开始 – 咱们期待着与社区在更多方面单干。咱们特地对社区在增量 EDS 方面的工作感兴趣。EDS 端点占了更新量的最大局部,这对管制立体和 Envoy 造成了不必要的压力。

咱们要非常感谢 Kinvolk 的人员对 Envoy 的奉献:Alban Crequy, Andrew Randall, Danielle Tal, 特地是 Krzesimir Nowak 的杰出工作。咱们也要感激 Envoy 社区的反对和尖锐的审查:Adi Peleg, Dmitri Dolguikh, Harvey Tuch, Matt Klein, 和 Mark Roth。与你们所有人单干是一次很好的经验。

这是咱们通向服务网格之旅的系列文章的第一篇,敬请期待。

关注 ” 云原生指北 ” 公众号
(转载本站文章请注明作者和出处盛世浮生,请勿用于任何商业用途)

正文完
 0