06:服务注册与发现NetFixEureka

Eureka简介

  • Eureka是基于REST(Representational State Transfer)服务,主要以AWS云服务为支撑,提供服务发现并实现负载均衡和故障转移。我们称此服务为Eureka服务。
  • Eureka提供了Java客户端组件,Eureka Client,方便与服务端的交互。客户端内置了基于round-robin实现的简单负载均衡。
  • 在Netflix,为Eureka提供更为复杂的负载均衡方案进行封装,以实现高可用,它包括基于流量、资源利用率以及请求返回状态的加权负载均衡。

Eureka包含两个组件:Eureka Server和Eureka Client

Eureka Server提供服务注册服务

  • 各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。

EurekaClient通过注册中心进行访问

  • 是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。
  • 如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

Eureka架构

在这里插入图片描述

Eureka中的一些概念

  • Register :服务注册
    Eureka客户端向Eureka Server注册时,它提供自身的元数据,比如IP地址、端口等
  • Renew:服务续约
    Eureka客户端会每隔30秒发送一次心跳来续约。通过续约来告知Eureka Server该客户端仍然存在。
  • Fetch Registries:获取注册列表信息
    Eureka客户端从服务器获取注册表信息,将其缓存到本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒)更新一次。
  • Cancel:服务下线
    Eureka客户端在程序关闭时向Eureka服务器发送取消请求。
  • Eviction:服务剔除
    在默认情况下,当Eureka客户端90秒没有向Eureka服务器发送续约,Eureka服务器就会将该服务实例从服务注册列表删除。
  • 自我保护
    Eureka会定时剔除没有续约的服务,那就可能会出现一种极端情况,网络发生了异常,所有的服务都没有续约,那么EurekaServer就会剔除掉所有的服务,这显然不合理,于是就有了自我保护机制,当短时间内(15min)如果续约失败的比例达到了设置的阈值(85%),就会触发自我保护机制,该机制下,EurekaServer不会剔除服务,等到正常后再退出自我保护机制。自我保护开关(eureka.server.enable-self-preservation=true)。
    除了以上的特性外,Eureka的缓存机制也非常经典,下面详细介绍一下。

Eureka Server 数据存储

  • Eureka Server 的数据存储分了两层:数据存储层和缓存层。数据存储层记录注册到 Eureka Server 上的服务信息,缓存层是经过包装后的数据,可以直接在 Eureka Client 调用时返回。
  • Eureka Server 的数据存储层是双层的 ConcurrentHashMap
  • 第一层的 ConcurrentHashMap 的 key=spring.application.name 也就是客户端实例注册的应用名;value 为嵌套的 ConcurrentHashMap。
  • 第二层嵌套的 ConcurrentHashMap 的 key=instanceId 也就是服务的唯一实例 ID,value 为 Lease 对象,Lease 对象存储着这个实例的所有注册信息,包括 ip 、端口、属性等。
    在这里插入图片描述

Eureka Server 缓存机制

  • Eureka Server 为了提供响应效率,提供了两层的缓存结构,将 Eureka Client 所需要的注册信息,直接存储在缓存结构中。
  • 第一层缓存:readOnlyCacheMap,本质上是 ConcurrentHashMap,依赖定时从readWriteCacheMap 同步数据,默认时间为 30 秒。
  • readOnlyCacheMap : 是一个 CurrentHashMap 只读缓存,这个主要是为了供客户端获取注册信息时使用,其缓存更新,依赖于定时器的更新,通过和 readWriteCacheMap 的值做对比,如果数据不一致,则以 readWriteCacheMap 的数据为准。
  • 第二层缓存:readWriteCacheMap,本质上是 Guava 缓存。
  • readWriteCacheMap 的数据主要同步于存储层。当获取缓存时判断缓存中是否没有数据,如果不存在此数据,则通过 CacheLoader 的 load 方法去加载,加载成功之后将数据放入缓存,同时返回数据。
  • readWriteCacheMap 缓存过期时间,默认为 180 秒,当服务下线、过期、注册、状态变更,都会来清除此缓存中的数据。
  • Eureka Client 获取全量或者增量的数据时,会先从一级缓存中获取;如果一级缓存中不存在,再从二级缓存中获取;如果二级缓存也不存在,这时候先将存储层的数据同步到缓存中,再从缓存中获取。

Eureka Server常用配置

#服务端开启自我保护模式,前面章节有介绍
eureka.server.enable-self-preservation=true
#扫描失效服务的间隔时间(单位毫秒,默认是60*1000)即60秒
eureka.server.eviction-interval-timer-in-ms= 60000
#间隔多长时间,清除过期的 delta 数据
eureka.server.delta-retention-timer-interval-in-ms=0
#请求频率限制器
eureka.server.rate-limiter-burst-size=10
#是否开启请求频率限制器
eureka.server.rate-limiter-enabled=false
#请求频率的平均值
eureka.server.rate-limiter-full-fetch-average-rate=100
#是否对标准的client进行频率请求限制。如果是false,则只对非标准client进行限制
eureka.server.rate-limiter-throttle-standard-clients=false
#注册服务、拉去服务列表数据的请求频率的平均值
eureka.server.rate-limiter-registry-fetch-average-rate=500
#设置信任的client list
eureka.server.rate-limiter-privileged-clients=
#在设置的时间范围类,期望与client续约的百分比。
eureka.server.renewal-percent-threshold=0.85
#多长时间更新续约的阈值
eureka.server.renewal-threshold-update-interval-ms=0
#对于缓存的注册数据,多长时间过期
eureka.server.response-cache-auto-expiration-in-seconds=180
#多长时间更新一次缓存中的服务注册数据
eureka.server.response-cache-update-interval-ms=0
#缓存增量数据的时间,以便在检索的时候不丢失信息
eureka.server.retention-time-in-m-s-in-delta-queue=0
#当时间戳不一致的时候,是否进行同步
eureka.server.sync-when-timestamp-differs=true
#是否采用只读缓存策略,只读策略对于缓存的数据不会过期。
eureka.server.use-read-only-response-cache=true


################server node 与 node 之间关联的配置#####################33
#发送复制数据是否在request中,总是压缩
eureka.server.enable-replicated-request-compression=false
#指示群集节点之间的复制是否应批处理以提高网络效率。
eureka.server.batch-replication=false
#允许备份到备份池的最大复制事件数量。而这个备份池负责除状态更新的其他事件。可以根据内存大小,超时和复制流量,来设置此值得大小
eureka.server.max-elements-in-peer-replication-pool=10000
#允许备份到状态备份池的最大复制事件数量
eureka.server.max-elements-in-status-replication-pool=10000
#多个服务中心相互同步信息线程的最大空闲时间
eureka.server.max-idle-thread-age-in-minutes-for-peer-replication=15
#状态同步线程的最大空闲时间
eureka.server.max-idle-thread-in-minutes-age-for-status-replication=15
#服务注册中心各个instance相互复制数据的最大线程数量
eureka.server.max-threads-for-peer-replication=20
#服务注册中心各个instance相互复制状态数据的最大线程数量
eureka.server.max-threads-for-status-replication=1
#instance之间复制数据的通信时长
eureka.server.max-time-for-replication=30000
#正常的对等服务instance最小数量。-1表示服务中心为单节点。
eureka.server.min-available-instances-for-peer-replication=-1
#instance之间相互复制开启的最小线程数量
eureka.server.min-threads-for-peer-replication=5
#instance之间用于状态复制,开启的最小线程数量
eureka.server.min-threads-for-status-replication=1
#instance之间复制数据时可以重试的次数
eureka.server.number-of-replication-retries=5
#eureka节点间间隔多长时间更新一次数据。默认10分钟。
eureka.server.peer-eureka-nodes-update-interval-ms=600000
#eureka服务状态的相互更新的时间间隔。
eureka.server.peer-eureka-status-refresh-time-interval-ms=0
#eureka对等节点间连接超时时间
eureka.server.peer-node-connect-timeout-ms=200
#eureka对等节点连接后的空闲时间
eureka.server.peer-node-connection-idle-timeout-seconds=30
#节点间的读数据连接超时时间
eureka.server.peer-node-read-timeout-ms=200
#eureka server 节点间连接的总共最大数量
eureka.server.peer-node-total-connections=1000
#eureka server 节点间连接的单机最大数量
eureka.server.peer-node-total-connections-per-host=10
#在服务节点启动时,eureka尝试获取注册信息的次数
eureka.server.registry-sync-retries=
#在服务节点启动时,eureka多次尝试获取注册信息的间隔时间
eureka.server.registry-sync-retry-wait-ms=
#当eureka server启动的时候,不能从对等节点获取instance注册信息的情况,应等待多长时间。
eureka.server.wait-time-in-ms-when-sync-empty=0

Eureka Client 常用配置

#该客户端是否可用
eureka.client.enabled=true
#实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
eureka.client.register-with-eureka=false
#此客户端是否获取eureka服务器注册表上的注册信息,默认为true
eureka.client.fetch-registry=false
#是否过滤掉,非UP的实例。默认为true
eureka.client.filter-only-up-instances=true
#与Eureka注册服务中心的通信zone和url地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

#client连接Eureka服务端后的空闲等待时间,默认为30 秒
eureka.client.eureka-connection-idle-timeout-seconds=30
#client连接eureka服务端的连接超时时间,默认为5秒
eureka.client.eureka-server-connect-timeout-seconds=5
#client对服务端的读超时时长
eureka.client.eureka-server-read-timeout-seconds=8
#client连接all eureka服务端的总连接数,默认200
eureka.client.eureka-server-total-connections=200
#client连接eureka服务端的单机连接数量,默认50
eureka.client.eureka-server-total-connections-per-host=50
#执行程序指数回退刷新的相关属性,是重试延迟的最大倍数值,默认为10
eureka.client.cache-refresh-executor-exponential-back-off-bound=10
#执行程序缓存刷新线程池的大小,默认为5
eureka.client.cache-refresh-executor-thread-pool-size=2
#心跳执行程序回退相关的属性,是重试延迟的最大倍数值,默认为10
eureka.client.heartbeat-executor-exponential-back-off-bound=10
#心跳执行程序线程池的大小,默认为5
eureka.client.heartbeat-executor-thread-pool-size=5
# 询问Eureka服务url信息变化的频率(s),默认为300秒
eureka.client.eureka-service-url-poll-interval-seconds=300
#最初复制实例信息到eureka服务器所需的时间(s),默认为40秒
eureka.client.initial-instance-info-replication-interval-seconds=40
#间隔多长时间再次复制实例信息到eureka服务器,默认为30秒
eureka.client.instance-info-replication-interval-seconds=30
#从eureka服务器注册表中获取注册信息的时间间隔(s),默认为30秒
eureka.client.registry-fetch-interval-seconds=30

# 获取实例所在的地区。默认为us-east-1
eureka.client.region=us-east-1
#实例是否使用同一zone里的eureka服务器,默认为true,理想状态下,eureka客户端与服务端是在同一zone下
eureka.client.prefer-same-zone-eureka=true
# 获取实例所在的地区下可用性的区域列表,用逗号隔开。(AWS)
eureka.client.availability-zones.china=defaultZone,defaultZone1,defaultZone2
#eureka服务注册表信息里的以逗号隔开的地区名单,如果不这样返回这些地区名单,则客户端启动将会出错。默认为null
eureka.client.fetch-remote-regions-registry=
#服务器是否能够重定向客户端请求到备份服务器。 如果设置为false,服务器将直接处理请求,如果设置为true,它可能发送HTTP重定向到客户端。默认为false
eureka.client.allow-redirects=false
#客户端数据接收
eureka.client.client-data-accept=
#增量信息是否可以提供给客户端看,默认为false
eureka.client.disable-delta=false
#eureka服务器序列化/反序列化的信息中获取“_”符号的的替换字符串。默认为“__“
eureka.client.escape-char-replacement=__
#eureka服务器序列化/反序列化的信息中获取“$”符号的替换字符串。默认为“_-”
eureka.client.dollar-replacement="_-"
#当服务端支持压缩的情况下,是否支持从服务端获取的信息进行压缩。默认为true
eureka.client.g-zip-content=true
#是否记录eureka服务器和客户端之间在注册表的信息方面的差异,默认为false
eureka.client.log-delta-diff=false
# 如果设置为true,客户端的状态更新将会点播更新到远程服务器上,默认为true
eureka.client.on-demand-update-status-change=true
#此客户端只对一个单一的VIP注册表的信息感兴趣。默认为null
eureka.client.registry-refresh-single-vip-address=
#client是否在初始化阶段强行注册到服务中心,默认为false
eureka.client.should-enforce-registration-at-init=false
#client在shutdown的时候是否显示的注销服务从服务中心,默认为true
eureka.client.should-unregister-on-shutdown=true

Eureka Instance 常用配置

#服务注册中心实例的主机名
eureka.instance.hostname=localhost
#注册在Eureka服务中的应用组名
eureka.instance.app-group-name=
#注册在的Eureka服务中的应用名称
eureka.instance.appname=
#该实例注册到服务中心的唯一ID
eureka.instance.instance-id=
#该实例的IP地址
eureka.instance.ip-address=
#该实例,相较于hostname是否优先使用IP
eureka.instance.prefer-ip-address=false

Eureka注册中心组成

在这里插入图片描述
Eureka属于AP架构,高可用。

EurekaServer端源码–流程图

1:找到eurekaserver jar包,spi机制,找到其中的sping.factories文件,找到server服务端自动装配的类EurekaServerAutoConfiguration
2:此配置类中会配置一些Bean

  • EurekaServerConfig—初始化eureka相关配置
  • EurekaController—初始化接口,获取eurekaServer信息
  • PeerAwareInstanceRegistry—初始化集群注册表
  • PeerEurekaNodes—初始化集群节点集合
  • EurekaServerContext—基于eurekaServer注册配置表,集群节点集合及初始化eurekaServer上下文
  • EurekaServerBootstrap—启动eureka服务
  • FilterRegistrationBean—初始化Jersey过滤器

3:此配置类中@Import注解的实现类EurekaServerInitializerConfiguration,实现了SmartLifecycle接口
并且定义了isAutoStartup返回true,SmartLifecycle继承自Lifecycle,就会调用到Lifecycle的start方法

  • SmartLifecycle继承了Lifecycle,LifecycleProcessor继承了Lifecycle并且其中定义了onRefresh方法,在spring启动时刷新上下文时候就会调用到此方法。调用链路如下:
    1:spring启动刷新上下文------this.finishRefresh();
    2:LifecycleProcessor().onRefresh();
    3:this.startBeans(true);
    4:DefaultLifecycleProcessor.this.doStart
    5:start

4:start方法中新起了一个线程,启动eureka服务
5:初始化上下文------this.eurekaServerBootstrap.contextInitialized(this.servletContext);
6:发布eureka注册有效事件------this.publish(new EurekaRegistryAvailableEvent(this.getEurekaServerConfig()));
7:发布eureka服务启动成功事件------this.publish(new EurekaServerStartedEvent(this.getEurekaServerConfig()));
8:contextInitialized方法中

  • 初始化eureka环境------this.initEurekaEnvironment();
  • 初始化上下文------this.initEurekaServerContext();

9:初始化上下文------this.initEurekaServerContext()中------服务同步replicate

  • 从相邻节点复制注册表------this.registry.syncUp();
  • 获取相邻节点注册的服务实例------Applications apps = this.eurekaClient.getApplications();
  • 注册到本地------this.register(instance, instance.getLeaseInfo().getDurationInSecs(), true);

10:初始化上下文------this.initEurekaServerContext()中------服务剔除evict

  • registry.openForTraffic(this.applicationInfoManager, registryCount);
  • 修改服务实例状态为UP------applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
  • 开启一个定时任务,每隔60s清理没有续约的任务------postInit();
  • 定时任务------
this.evictionTimer.schedule((TimerTask)this.evictionTaskRef.get(), 
							this.serverConfig.getEvictionIntervalTimerInMs(), 
							this.serverConfig.getEvictionIntervalTimerInMs());
  • 定时任务run方法-----EvictionTask.run()------com.netflix.eureka.registry.AbstractInstanceRegistry.EvictionTask#run

EurekaClient端源码–流程图

如何开启服务注册进Eureka服务

  • EurekaClient的开启可以使用@EnableDiscoveryClient注解,也可以不使用这个注解,因为这个注解中的属性autoRegister默认为TRUE,如果我们不想某个服务注册进Eureka可以将这个属性设置为false(@EnableDiscoveryClient(autoRegister= false))

Client端流程

  • 1:EurekaClientAutoConfiguration中注解@AutoConfigureAfter中含有一个类EurekaDiscoveryClientConfiguration,
  • 2:这个类中会注入一个bean-Marker。此Marker正是EurekaClientAutoConfiguration所需要的,只有这个bean存在springboot才会在启动的时候注册这个EurekaClientAutoConfiguration-Bean.
  • 3:EurekaClientAutoConfiguration中配置了很多的Bean
3.1:EurekaClientConfigBean------初始化EurekaClient相关配置
3.2:EurekaInstanceConfigBean------client实例相关配置信息
3.3:EurekaServiceRegistry------服务注册
3.4:EurekaHealthIndicator------心跳检测
3.5:EurekaClient
  • 4:其中EurekaClient很重要,EurekaClient是对DiscoveryClient包装。
  • 5:DiscoveryClient的构造函数中会初始化各种任务,在initScheduledTasks中会初始化定时拉取服务注册信息更新本地注册表和服务续约任务;初始化定时服务注册任务。后续具体流程请查看流程图。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值