netflix-eureka 服务注册与容错

栏目: Java · 发布时间: 4年前

内容简介:在2015-2016,我们将单体应用程序重新设计为微服务,并选择(Spring Cloud Netflix)通过自动配置, Spring 环境以及其他 Spring 编程模型习惯用法为 Spring时间流逝,我们逐渐对框架更加熟悉,甚至还贡献了一些代码。我认为我已经知道了够多了, 便开始研究 Eureka 冗余和故障转移。一个概念的快速证明不起作用,当我挖掘更多时,我遇到了其他可怜的灵魂在互联网上搜索类似的信息。不幸的是, 找不到啥。值得赞扬的是,Spring Cloud 文档相当不错,而且还有

Spring Cloud Netflix Eureka - 隐藏手册

介绍

在2015-2016,我们将单体应用程序重新设计为微服务,并选择 Spring Cloud Netflix 作为基础。

(Spring Cloud Netflix)通过自动配置, Spring 环境以及其他 Spring 编程模型习惯用法为 Spring

时间流逝,我们逐渐对框架更加熟悉,甚至还贡献了一些代码。我认为我已经知道了够多了, 便开始研究 Eureka 冗余和故障转移。一个概念的快速证明不起作用,当我挖掘更多时,我遇到了其他可怜的灵魂在互联网上搜索类似的信息。不幸的是, 找不到啥。值得赞扬的是,Spring Cloud 文档相当不错,而且还有 Netflix Wiki ,但没有一个达到我想要的详细程度。这篇文章试图弥合这一差距。我假设您对 Eureka 和服务发现有一些基本的了解,所以如果您是新手,请在阅读 Spring Cloud 文档后再回来。

基础架构

netflix-eureka 服务注册与容错

Netflix 的高级架构,遵循 Apache License v2.0 许可。

Eureka 有两个基本组件,服务器和客户端。引用 Netflix Wiki:

Eureka 是一种基于 REST(Representational State Transfer)的服务,主要用于 AWS 云,用于定位服务,以实现中间层服务器的负载均衡和故障转移。我们将此服务称为 Eureka Server。Eureka 还附带了一个基于 Java 的客户端组件 Eureka Client,它使与服务的交互变得更加容易。客户端还有一个内置的负载均衡器,可以进行基本的循环负载均衡。

Eureka 客户端应用程序称为实例。客户端应用程序和 Eureka 客户端之间存在细微差别; 前者是您的应用程序,后者是框架提供的组件。

Netflix 设计的 Eureka 具有高度动态性。有一般属性,也有一些专门属性用于定义了在一般属性的更新查询时间间隔。这是一种常见的做法,这意味着大多数这些属性可以在运行时更改,并在下一个刷新周期中被感知。例如,客户端用于向 Eureka 注册的 URL 可以更改,并在5分钟后被感知(可配置eureka.client.eurekaServiceUrlPollIntervalSeconds )。大多数用户不需要这样的动态更新,但如果你想这样做,可以找到所有配置选项,如下所示:

  • 对于 Eureka 服务器配置:

org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean 实现com.netflix.eureka.EurekaServerConfig。所有属性都具有eureka.server 前缀。

  • 对于 Eureka 客户端配置:

org.springframework.cloud.netflix.eureka.EurekaClientConfigBean 实现 com.netflix.discovery.EurekaClientConfig。所有属性都有 eureka.client 前缀。

  • 对于Eureka实例配置:

org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean 实现(间接)com.netflix.appinfo.EurekaInstanceConfig。所有属性都有 eureka.instance 前缀。

有关更多体系结构的详细信息,请参阅 Netflix Wiki。

Eureka实例和客户

在 Eureka 中通过 eureka.instance.instanceId 识别实例, 如果不存在则用eureka.instance.metadataMap.instanceId。实例发现彼此使用 eureka.instance.appName,该值在 Spring Cloud 默认使用 spring.application.name 或者 UNKNOWN 如果前者未定义。您需要进行设置,spring.application.name 因为具有相同名称的应用程序在 Eureka 服务器中聚集在一起。不需要设置eureka.instance.instanceId,因为它默认值设置为 CLIENT IP:PORT,但如果你想设置它,则appName必须在集群范围内是唯一的。还有一个 eureka.instance.virtualHostName,但它没有被 Spring 使用,并且设置为 spring.application.name 或 UNKNOWN 如上所述。

如果 registerWithEureka 是 true,则实例使用给定的 URL 向 Eureka 服务器注册; 然后,它每30秒发送一次心跳(可配置 eureka.instance.leaseRenewalIntervalInSeconds)。如果服务器没有收到心跳,则在eureka.instance.leaseExpirationDurationInSeconds 从注册表中删除实例之前等待90秒(可配置),然后禁止该实例的流量。发送心跳是一项异步任务; 如果操作失败,则以指数方式后退2倍,直到eureka.instance.leaseRenewalIntervalInSeconds * eureka.client.heartbeatExecutorExponentialBackOffBound 达到最大延迟。注册 Eureka 的重试次数没有限制。

心跳与将 实例信息更新 到 Eureka 服务器不同。每个实例都由 com.netflix.appinfo.InstanceInfo 表示,它是关于实例的一堆信息。它将 InstanceInfo 会定期发送到Eureka 服务器,从启动后40s开始(可配置eureka.client.initialInstanceInfoReplicationIntervalSeconds),然后每30秒开始一次(可配置eureka.client.instanceInfoReplicationIntervalSeconds)。

如果 eureka.client.fetchRegistry 是 true,则客户端在启动时获取 Eureka 服务器注册表并在本地进行缓存。从那时起,它只是获取增量(这可以通过设置来关闭 eureka.client.shouldDisableDelta 到 false,尽管这会是浪费带宽)。注册表获取是每30秒调度一次的异步任务(可配置eureka.client.registryFetchIntervalSeconds)。如果操作失败,则按指数2倍后退,直到eureka.client.registryFetchIntervalSeconds * eureka.client.cacheRefreshExecutorExponentialBackOffBound 达到最大延迟。获取注册表信息的重试次数没有限制。

客户端任务由 com.netflix.discovery.DiscoveryClient 安排, 这个类是对 Spring Cloud 的org.springframework.cloud.netflix.eureka.CloudEurekaClient 的扩展实现。

为什么用 Eureka 实例需要这么长时间?

大部分都是从 spring-cloud-netflix#373 复制而来的。

客户注册

第一次心跳在启动后发生30s(如前所述),因此实例在此间隔之前不会出现在 Eureka 注册表中。

服务器响应缓存

服务器维护一个每30秒更新一次的响应缓存(可配置 eureka.server.responseCacheUpdateIntervalMs)。因此,即使实例刚刚注册,它也不会出现在对 /eureka/apps REST 端点的调用结果中。但是,实例可能会在注册后出现在 Eureka Dashboard 上。这是因为仪表板绕过了 REST API 使用的响应缓存。如果您知道instanceId,您仍然可以通过调用从 Eureka 获取有关它的一些详细信息 /eureka/apps/<appName>/<instanceId> 。此端点不使用响应缓存。

因此,其他客户端可能需要另外30秒来发现新注册的实例。

客户端缓存刷新

Eurekac客户端维护注册表信息的缓存。此缓存每30秒刷新一次(如前所述)。因此,在客户端决定刷新其本地缓存并发现其他新注册的实例之前,可能还需要30秒。

LoadBalancer 刷新

Ribbon 使用的负载均衡器从本地 Eureka 客户端获取其信息。Ribbon 还维护一份本地缓存,以避免为每个请求调用客户端。此缓存每30秒刷新一次(可配置 ribbon.ServerListRefreshInterval)。因此,在 Ribbon 可以使用新注册的实例之前可能还需要30秒。

最后,在新注册的实例开始接收来自其他实例的流量之前,可能需要2分钟。

Eureka 服务器

Eureka 服务器具有对等感知模式,在该模式下,它跨其他 Eureka 服务器复制服务注册表,以提供负载平衡和弹性。对等感知模式是默认模式,因此 Eureka 服务器也充当 Eureka 客户端向对等体上注册给定的 URL。这就是你应该如何在生产中运行 Eureka,但是对于演示或概念验证,你可以通过设置 registerWithEureka 为 false 采用独立模式运行。

当 Eureka 服务器启动时,它会尝试从对等的 Eureka 节点获取所有注册表信息。对每个对等体重试此操作5次(可配置 eureka.server.numberRegistrySyncRetries)。如果由于某种原因此操作失败,则服务器不允许客户端获取注册表信息5分钟(可配置 eureka.server.getWaitTimeInMsWhenSyncEmpty)。

Eureka 的对等感知意识,通过所谓的“自我保护”的概念引入一个全新水平的复杂性(可以通过设置eureka.server.enableSelfPreservation 为 false 来关闭)。事实上,在网上看,这是我看到大多数人绊倒的地方。来自 Netflix Wiki:

当 Eureka 服务器启动时,它会尝试从相邻节点获取所有实例注册表信息。如果从某个节点获取信息时出现问题,服务器会尝试所有对等体直到放弃。如果服务器能够成功获取所有实例,则会根据该信息设置应接收的续订阈值。如果有任何时间,续订低于为该值配置的百分比,则服务器会停止使用 实例过期 机制, 以保护当前实例注册表信息。

数学运算如下:如果有两个客户端注册到 Eureka 实例,每个客户端每30秒发送一次心跳,该实例应该在一分钟内收到4次心跳。Spring 为此添加了一个较低的最小值1(可配置eureka.instance.registry.expectedNumberOfRenewsPerMin),因此实例希望每分钟接收5个心跳。然后将其乘以0.85(可配置eureka.server.renewalPercentThreshold)并四舍五入到下一个整数,这使我们再次回到 5。如果 Eureka 在15分钟内收到的心跳少于5次(可配置 eureka.server.renewalThresholdUpdateIntervalMs),它将进入自我保护模式并 不再让 已经注册的 实例过期

Eureka 服务器隐含假设客户端以每30秒固定的速率发送心跳。如果注册了两个实例,则服务器希望(2 2 + 1 ) 0.85 = 5每分钟都接收一次心跳。如果续订率低于此值,则激活自保护模式。现在,如果客户端发送心跳的速度要快得多(例如,每隔10秒),则服务器每分钟接收12次心跳,并且即使其中一个实例发生故障,也会持续接收6次/分钟。因此,即使应该是自保护模式也不会被激活。这就是改变 eureka.client.instanceInfoReplicationIntervalSeconds 不可取的原因。如果必须的话, 你可以修改一下 eureka.server.renewalPercentThreshold 的值。

Eureka 对等实例不考虑预期的续约数量,但他们的心跳被计入在最后一分钟收到的续约数量。在对等感知模式下,心跳可以转到任何 Eureka 实例; 这在运行负载均衡器或 Kubernetes 服务后很重要,其中心跳以循环模式(通常)发送到每个实例。

在更新超过阈值之前,Eureka服务器不会退出自我保护模式。这可能导致客户端获取不再存在的实例。请参阅了解 Eureka Peer to Peer Communication .

还有一件事:在同一主机上运行多个 Eureka 服务器。Netflix 代码(com.netflix.eureka.cluster.PeerEurekaNodes.isThisMyUrl)过滤掉同一主机上的对等 URL。这可能是为了防止服务器注册为自己的对等体(我在这里猜测),但由于它们不检查端口,因此除非 Eureka 主机名eureka.client.serviceUrl.defaultZone 不同,否则对等感知不起作用。这种情况的Hack解决方法是定义唯一的主机名,然后在 /etc/hosts 文件(或它的Windows等价物)将它们映射到 127.0.0.1 了。Spring Cloud doc讨论了这种解决方法,但没有提到为什么需要它。现在你知道了。

区域和可用区域

netflix-eureka 服务注册与容错

AWS Regions 和可用 Zones。

Eureka 旨在在 AWS 中运行,并使用许多特定于 AWS 的概念和术语。Regions 和 Zones 是两个这样的东西。来自 AWS doc:

Amazon EC2 托管在全球多个地点。这些位置由 Regions 和可用 Zones 组成。每个地区都是一个独立的地理区域。每个区域都有多个孤立的位置,称为可用Zones...每个区域都是完全独立的。每个可用 Zones 都是隔离的,但区域中的可用 Zones 通过低延迟链接连接。

Eureka 仪表板显示 环境数据中心 。的值被分别设置为 test 与 default,通过使用com.netflix.config.ConfigurationManager 设置 org.springframework.cloud.netflix.eureka.server.EurekaServerBootstrap。有各种查找和回退,因此如果由于某种原因需要更改它们,请参阅上述类的源代码。

Eureka 客户端默认情况下更喜欢相同的区域(可配置eureka.client.preferSameZone)。来自com.netflix.discovery.endpoint.EndpointUtils.getServiceUrlsFromDNS Java doc:

从DNS获取所有 Eureka 服务 URL 的列表,以便 Eureka 客户端与之交谈。客户端从其区域中获取服务 URL,然后随机故障转移到其他区域。如果同一区域中有多个服务器,则客户端会再次随机选择一个服务器。这样,流量将在发生故障时分发。

Ticket spring-cloud-netflix#203 在撰写本文时是开放的,其中有几个人谈论 Regions和 Zones。我没有验证,所以我无法评论Regions和 Zones如何与 Eureka一起使用。

高可用性(HA)

大部分都是从 spring-cloud-netflix#203 中复制而来的。

HA 策略似乎是一个主要的 Eureka 服务器(server1)与备份(server2)。

通过配置(或 DNS 或 /etc/hosts )向客户端提供 Eureka 服务器列表

客户端尝试连接server1; 在这一点上,server2坐着闲着。

如果server1不可用,客户端将从列表中尝试下一个。

当server1重新上线时,客户端会重新使用server1。

当然server1,server2可以在对等感知模式下运行,并且可以复制其注册表。但这与客户注册正交。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程之魂

编程之魂

Federico Biancuzzi、Shane Warden / 闫怀志 / 电子工业出版社 / 2010-04 / 59.80元

本书是27位杰出的设计师与你分享他们的智慧和经验。书中以问答方式告诉为什么要创建某种编程语言、它在技术上如何开发、如何教授和学习,以及它如何顺应时代发展等。你会发现构建成功编程语言所需的思想和步骤,它广受欢迎的原因,以及如何处理程序员常见的问题。因此,如果你想深入学习设计成功编程语言的思想,本书会对你大有帮助。一起来看看 《编程之魂》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具