丹灶网站设计,wordpress文章分集,北京做网站一般多少钱,可信网站证书1、Eureka Server服务端会做什么 1、服务注册 Client服务提供者可以向Server注册服务#xff0c;并且内部有二层缓存机制来维护整个注册表#xff0c;注册表是Eureka Client的服务提供者注册进来的。 2、提供注册表 服务消费者用来获取注册表 3、同步状态 通过注册、心跳机制…1、Eureka Server服务端会做什么 1、服务注册 Client服务提供者可以向Server注册服务并且内部有二层缓存机制来维护整个注册表注册表是Eureka Client的服务提供者注册进来的。 2、提供注册表 服务消费者用来获取注册表 3、同步状态 通过注册、心跳机制和 Eureka Server同步当前客户端的状态,这里就包括服务提供者和服务消费者。 2、Eureka Server的问题
问题 1、Eureka Server的自我保护机制是怎么实现怎么做到15分钟内服务心跳失败比例高于85%。 2、自我保护机制触发后有哪些功能会被开启 1、不再从注册列表中移除因为长时间没收到心跳而应该过期的服务,冷却时间是多久 2、仍然能够接受新服务的注册和查询注册表请求但是不会被同步到其它节点上 3、当网络稳定时当前实例新的注册信息会被同步到其它节点中怎么判断网络恢复 集群问题
Eureka Server集群中Eureka Server节点A和Eureka Server节点B是怎么通过P2P的方式完成服务注册表的同步? Eureka Server集群中同一个区域的Eureka Client怎么做到优先和同区域内的Eureka Server进行通信的? Eureka Client服务提供者向Eureka Server注册如果某个节点失败自动切换到其他节点是怎么做到的? Eureka Server什么时候会自动退出自我保护模式 二、源码概述
1、EurekaServer启动
EnableEurekaServer-import(EurekaServerMarkerConfiguration)-注册Bean(EurekaServerMarkerConfiguration.Marker)-Marker激活了EurekaServerAutoConfiguration这个配置类2、EurekaServerAutoConfiguration主要包含以下内容 1、创建Bean【EurekaServerConfigBean】是一个配置类EurekaServer的所有配置项都是EurekaServerConfigBean这个类里面。 2、创建Bean【EurekaController】也就是我们通过url可以访问EurekaServer后台。 3、创建Bean【PeerAwareInstanceRegistry】处理注册表的类这个类也会发布事件发布了注册事件和取消事件默认没有监听者需要自己实现 4、创建Bean【PeerEurekaNodes】初始化了集群节点集合 5、创建Bean【EurekaServerContext】专业名称叫【EurekaServer上下文】这个Bean的生成是基于上面创建的Bean: eureka server配置,注册表,集群节点集合来生成。而EurekaServerContext的作用就是初始化eurekaServer上下文里面会做很多事情。 6、创建Bean:【EurekaServerBootstrap】Eureka Server的启动类 7、创建Bean:【FilterRegistrationBean】主要是对Jersey过滤器的包装,那么这个过滤器干嘛用的 ? 到此EurekaServerAutoConfiguration的创建Bean的任务完成了但是EurekaServerAutoConfiguration里面还有一Import(EurekaServerInitializerConfiguration)注解
3、EurekaServerInitializerConfiguration
EurekaServerInitializerConfiguration里面有个start方法里面会拿到上面注册Bean【EurekaServerBootstrap启动类】来启动Eureak。 然后在通过生成的【EurekaServer上下文】开始初始化初始化的时候会调用registry.syncUp方法从相邻的eureka节点复制注册表通过http调用相邻节点获取所有服务实例。
在通过上面的【PeerAwareInstanceRegistry】把实例注册到本地这里的实例是指EurekaClient的服务提供者同时PeerAwareInstanceRegistry里面还有一个【Timer】这个是定时任务清理30s没有续约的任务、服务剔除超过90s没过来续约的服务。
原文地址跳转
三、下面通过代码原理说下实现逻辑 1、服务注册 2、服务续约 3、服务剔除 4、服务下线 5、服务发现 6、集群信息同步 1、服务注册
流程服务提供者请求EurekaServer端某个节点注册服务
EurekaClient端
Bean 【EurekaAutoServiceRegistration】
通过com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient#register向EurekaServer注册服务。EurekaServer端
EurekaServer收到请求,请求进到ApplicationResource#addInstance方法里面调用【BeanPeerAwareInstanceRegistry】#register方法
里面先发布一个Event事件但是Spring没有监听这个事件这个是留给我们自己拓展用的在register里面还有一个很重要的事做就是注册:
1、首先是设置服务的过期时间90s
2、调用父类完成服务注册
3、在完成集群信息同步同步给其他节点。重点看调用【父类完成注册】先从注册表的集合中获取服务注册信息
1、如果注册表存在那么说明冲突了就判断哪2个节点的活跃时间比较靠前保留节点时间最新的节点
2、如果不存在就新建将EurekaClient的服务提供者封装成InstanceInfo对象, InstanceInfo存放了注册信息最后操作时间注册时间过期时间
剔除时间等信息再把这个InstanceInfo对象存到注册表中去。至此一个服务注册的流程就完成了注意注册表是一个MapString, MapString, LeaseInstanceInfo对象
1、最外层的key是AppName,注册进来的服务的服务名 , value MapString, LeaseInstanceInfo value表示这个服务名对应多个实例节点
2、MapString, LeaseInstanceInfo这个Mapkey是ip端口value是LeaseInstanceInfo对象也就是这个实例的更多信息比如过期时间最近活跃时间等等。2、服务续约
服务续约由Eureka-client端主动发起请求Eureka服务端间隔时间30sEureka服务端收到请求刷新节点的活跃时间。因为Eureka服务端有定时任务就是基于这个活跃时间来考虑是否剔除服务。
Eureka-client端
请求Eureka服务端由DiscoveryClient#renew方法完成主要是发送http请求每隔30秒进行一次续约,
里面调用AbstractJerseyEurekaHttpClient#sendHeartBeat方法Eureka-server端
在Eureka-server端服务续约的调用链与服务注册基本相同
InstanceRegistry#renew() - PeerAwareInstanceRegistry#renew()- AbstractInstanceRegistry # renew() 主要逻辑还是AbstractInstanceRegistry的renew方法renew的方法逻辑操作非常简单它的本质就是修改服务的【最后更新时间】。将最后更新时间改为【系统当前时间】【服务的过期时间】3、服务剔除
服务主要是Eureka服务端通过定时任务检测注册节点的【活跃时间】如果超过90s就会剔除。
Eureka-server端
当Eureka-server发现有的实例没有续约超过一定时间则将该服务从注册列表剔除该项工作由一个定时任务完成的。由下面方法完成
AbstractInstanceRegistry # postInit()定时任务前面说了在【EurekaServer上下文】初始化的时候添加了一个Timer定时器定时器关联的任务是EvictionTask的run方法在执行任务中
调用剔除方法 evict(), 主要是拿到注册表的所有实例挨个遍历判断【系统当前时间 最后更新时间过期时间预留时间】
并且新建实例列表expiredLeases用来存放过期的实例。当该条件成立时认为服务过期在Eureka中过期时间默认定义为3个心跳的时间一个心跳是30秒因此过期时间是90秒。
将该过期实例放入上面创建的expiredLeases列表中。注意这里仅仅是将实例放入List中并没有实际剔除。因为要判断是否超过阈值了如果超过就从里面取随机数随机剔除实例ID注意expiredLeases里面存的是多个服务的实例不是某一个服务的所有实例。下线的时候从里面取随机数所以有可能某个服务的所有实例全部被剔除都有可能。在实际剔除任务前需要提一下eureka的自我保护机制
当1分钟内心跳失败的服务大于一定比例时会触发自我保护机制。这个值在Eureka中被定义为85%一旦触发自我保护机制
Eureka会尝试保护其服务注册表中的信息不再删除服务注册表中的数据。1分钟是怎么统计数量的哪些节点保留? 哪些节点删除?答使用了随机算法进行剔除
举个例子假如当前共有100个服务那么剔除阈值为85%也就是最多剔除15个如果list中有60个服务那么就会从60个服务里面取15个。有可能一个服务的所有节点全部被剔除。剔除的节点被放到一个queue里面这个里面存的是最近剔除的节点在集群同步或者拉取注册表的时候要用到。关于自我保护
首先是阈值是85%比如100个阈值是85%那么一次最多剔除15个当定时任务进来发现100个里面有10个失效那么10小于【最大阈值】那就剔除10个如果20个失效20个大于15所以最多剔除15个这15个怎么选
通过for循环15次每次生成一个随机数这个随机数是从20里面取1、自我保护时期不能进行服务剔除操作
2、过期操作是分批进行
3、服务剔除是随机逐个剔除均匀分布在所有应用中其实也不算均匀是随机抽
4、服务剔除是一个定时任务默认60秒一次问题自我保护时期不能进行服务剔除操作这个是怎么做到的首先是定义了2个变量一个是【期望续约数】一个是【前一分钟实际的续约数】。
这个【期望续约数】是通过公式算出来了比如20个实例正常情况下1分钟的话会续约40次
那么期望的续约数应该是40*85%34个而如果实际契约数超过这个数量比如35
那么EurekaServer认为服务恢复正常了应该关闭自我保护机制。
注意期望续约数是一个动态值每次会重行计算的。比如服务下线或者上线期望的数量是会加1或者减1的。问题实际续约数是怎么算出来的
因为剔除的定时任务是1分钟一次所以有个定时任务专门设置【前一分钟实际续约数量】MeasuredRate也是60秒一次他里面定义了2个变量一个是【一分钟内的续约】数一个是【上一分钟的续约数】服务每次注册就会加1服务下线就减1当定时任务跑的时候就会把一分钟的续约数赋值给【上一分钟的续约数】然后再把【一分钟内的续约】置0自我保护机制详细解读跳转 代码流程跳转
4、服务下线
当eureka-client关闭时不会立刻关闭需要先发请求给eureka-server服务端告知自己要下线了。
Eureka-client端
Eureka客户端请求EurekaServer服务端通过DiscoveryClient#shutdown方法调用EurekaServer服务端Eureka-server端
收到请求进到AbstractInstanceRegistry#cancel方法, 最终还是调用了和服务剔除中一样的方法remove掉了注册表中的实例5、服务发现
是指EurekaClient 消费者通过Http调用EurekaServer服务端接口获取注册表信息
Eureka-client端 DiscoveryClient#getInstances方法可以根据服务id获取服务实例列表。那么这里就有一个问题了我们还没有去调用微服务那么服务列表是什么时候被拉取或缓存到本地的服务列表的呢 EurekaDiscoveryClient # getInstances() - DiscoveryClient # getInstancesByVipAddress() - DiscoveryClient #getInstancesByVipAddress2() -Applications # getInstancesByVirtualHostName() 这里居然不是走的http是读的本地缓存。Applications中的getInstancesByVirtualHostName方法里面有一个virtualHostNameAppMap的Map集合中已经保存了当前所有注册到eureka的服务列表。
private final MapString, VipIndexSupport virtualHostNameAppMap;
也就是说在我们没有手动去调用服务的时候该集合里面已经有值了说明在Eureka-server项目启动后会自动去拉取服务并将拉取的服务缓存起来。那么追根溯源来查找一下服务的发现究竟是什么时候完成的。回到DiscoveryClient这个类
在它的构造方法中定义了任务调度线程池cacheRefreshExecutor定义完成后调用initScheduledTask方法
通过fetchRegistry方法来拉取不过分2种情况【增量拉取】还是【全量拉取】【全量拉取】当缓存为null或里面的数据为空或强制时进行全量拉取执行getAndStoreFullRegistry方法
【增量拉取】: 只拉取修改的。执行getAndUpdateDelta方法虽然这里是拉增量但是如果没拉到数据还是会拉全量的数据然后就是更新操作更新也有类型是delete还是Modify,added,这里有个细节校验就是拿hashCode和缓存的HashCode对比是否一致如果一致说明数据没有变动如果不一致那就说明本地和远程数据不一样需要重新再拉一次对服务发现过程进行一下重点总结 1、服务列表的拉取并不是在服务调用的时候才拉取而是在项目启动的时候就有定时任务去拉取了这点在DiscoveryClient的构造方法中能够体现 2、服务的实例并不是实时的Eureka-server中的数据而是一个本地缓存的数据 3、缓存更新根据实际需求分为全量拉取与增量拉取。 6、集群信息同步
Eureka-server端
集群信息同步发生在Eureka-server之间之前提到在PeerAwareInstanceRegistryImpl类中在执行register方法注册微服务实例完成后
执行了集群信息同步方法replicateToPeers首先遍历集群节点用以给各个集群信息节点进行信息同步。最终发送http请求请求各个EureakServer节点。
调用EurekaServer的ApplicationResource类里面的addInstance注意EurekaClient注册的时候也是调的这个方法
单独注册时isReplication的值为false集群同步时为trueEureka三级缓存
服务端的缓存机制 服务端采用三级缓存registryreadWriteCacheMapreadOnlyCacheMap来存储注册表信息。 三级缓存的目的是为了将注册服务和获取服务区分开避免了高并发的同时对一个缓存的读写操作有效避免读写冲突。保证性能。 一级缓存 ConcurrentHashMapKey,Value registry 服务一开始注册进来的地方 二级缓存 LoadingKey,Value readWriteCacheMap本质上是guava的缓存包含失效机制保存服务信息的对外输出数据结构。 三级缓存 ConcurrentHashMapKey,Value readOnlyCacheMap 本质上是HashMap无过期时间保存服务信息的对外输出数据结构。 设置缓存
1、客户端将服务信息注册在一级缓存registry中。每30s一次心跳续约
2、一级缓存registry收到注册信息后先清空二级缓存readWriteCacheMap中的注册信息然后在同步新数据给readWriteCacheMap二级缓存。
3、二级缓存按照30s一次的频率给三级缓存readOnlyCacheMap同步数据缓存获取
4、其他的客户端连接注册中心Server 30s一次的频率从三级缓存readOnlyCacheMap中获取如果readOnlyCacheMap中获取不到则直接去一级缓存registry中获取。缓存更新
5、一级缓存中默认每隔60s检查服务续期如果90秒内服务还没有续期则删除注册信息。同时同步给二级三级缓存。
6、服务下线时一级缓存registry中的注册信息删除同时删除二级缓存的数据。30s后二级同步三级缓存时发现二级缓存已失效则删除三级缓存的注册表信息。则会期间会有时间的延迟。
7、二级缓存的默认有效期是180s3min3min后数据会失效然后二级缓存数据清空。三级缓存的弊端 三级缓存的问题很明显就是服务下线之后不能及时通知到三级缓存中注册信息的获取者客户端拿到的注册信息不是实时的。当让客户端的获取也不是实时的要间隔30s才会去主动获取