会用eureka?你了解原理吗?
Posted Java爱好狂.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了会用eureka?你了解原理吗?相关的知识,希望对你有一定的参考价值。
一、服务注册发现简要流程
首先通过以下一幅图简单看下eureka的服务注册发现流程是什么样的:
1、服务提供者提供应用服务,注册到eureka server中。
2、服务消费者每30秒去去注册中心拉取服务的ip,端口,接口地址等信息。
3、服务消费者拉取到服务提供者的应用信息后,可以直接去调用服务提供者的接口。
二、服务发现注册的整体流程
三、主要概念及原理
服务注册
服务注册的原理主要涉及到eureka server的存储结构,采用一个三层缓存的结构。具体内部的实现逻辑参考二中的图。
层级 | 名称 | 实现方式 | 更新方式 | 数据变更 |
---|---|---|---|---|
第一层 | readOnlyCacheMap(只读) | ConcurrentHashMap | 定时更新(默认30s) | 定时拉取readWriteCacheMap |
第二层 | readWriteCacheMap(读写) | guava | 实时更新 | guava的load机制 |
第三层 | register(注册表) | 双层ConcurrentHashMap | 实时更新 | 客户端的注册、续约、下线 |
服务续约
当服务提供者完成服务信息注册后,会维持一个心跳,定时向eureka server 发送rest请求,告诉其还活着。默认心跳间隔30s。
服务获取
eureka client会定期(默认30s)向eureka server获取获取注册的服务信息,这个获取分为全量获取
和增量获取
。
默认配置下,当客户端首次启动后,会向服务端发起一次全量获取并缓存本地信息,之后每隔30s发起一次增量获取,更新本地缓存。
服务调用
通常服务间调用使用组件feign,发起rest请求;
其内集成了ribbon,ribbon默认使用了轮询的负载策略,会将eureka client拉取的注册信息拉取到自己这,实现负载。
服务下线
表示要从注册中心删除该服务的注册信息,使该服务不能被调用。
服务下线的方式:
方式 | 实现 | 效果 |
---|---|---|
直接停服务 | 直接kill服务 | 90s内注册中心检测到服务无续约,才删除,无法立即下线 |
通过注册中心接口强制下线 | 向eureka 注册中心发送delete | 默认30s的心跳机制,如果在这段时间没有停掉服务,那么会让该服务再次上线 |
客户端主动下线 | @GetMapping("/offline") public void offline() DiscoveryManager.getInstance().shutdownComponent(); | 优雅的下线服务 |
失效剔除
在eureka server中有一个定时任务Evict,该任务默认每60s执行一次,其作用域在readWriteCacheMap和register上。
当有服务提供者在默认90s时间内,没有进行服务续约,当Evict执行时,会对这样失效的注册信息进行剔除。通常是宕机的服务或者强制kill的服务。
自我保护
官方定义:自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。
Eureka Server在运行期间会统计心跳失败的比例在15分钟内是否低于85%,如果出现低于的情况,Eureka Server会将当前的实例注册信息保护起来,不会让它们立刻过期。
此配置在默认环境下开启。
自我保护存在的问题:在保护期间,服务挂掉,导致服务无法下线,造成调用接口失败。
eureka宕机后,服务之间仍然可以通信。
因为eureka client本地缓存注册表信息,当eureka server宕机后服务间仍然可以访问,但是服务提供端和服务消费端又分为以下情况:
- 当服务消费端重启后,本地缓存失效,与服务提供端的映射不存在了,无法进行服务调用。
- 当服务提供端重启后,在服务调用端的本地缓存中,仍然保存有在eureka宕机前的缓存信息,可以正常调用服务。
集群注册信息同步
-
eureka采用的同步方式是
peer to peer(对等复制)
,副本间不分主从,任何副本都可以接收写操作,然后每个副本间互相进行数据更新。 -
Eureka Server 本身依赖了 Eureka Client,也就是每个 Eureka Server 是作为其他 Eureka Server 的 Client。
-
Eureka Server 启动后,会通过 Eureka Client 请求其他 Eureka Server 节点中的一个节点,获取注册的服务信息,然后复制到其他 peer 节点。
-
Eureka Server 每当自己的信息变更后,例如 Client 向自己发起注册、续约、注销请求, 就会把自己的最新信息通知给其他 Eureka Server,保持数据同步。
-
存在的问题:
-
(1)每个节点都可以进行写操作,会导致数据冲突。
-
(2)如果自己的信息变更是另一个Eureka Server同步过来的,这是再同步回去的话就出现数据同步死循环了。
-
-
问题(1)解决方案:
Eureka 是通过 lastDirtyTimestamp 这个类似版本号的属性来解决该问题。 lastDirtyTimestamp 是注册中心里面服务实例的一个属性,表示此服务实例最近一次变更时间。
-
问题(2)解决方案:
Eureka Server 在执行复制操作的时候,使用 HEADER_REPLICATION 这个 http header 来区分普通应用实例的正常请求,说明这是一个复制请求,这样其他 peer 节点收到请求时,就不会再对其进行复制操作,从而避免死循环。
eureka保证CAP中的AP
通过前面了解到,eureka并没有保证数据的强一致性,只保证了数据的最终一致性,通过集群模式保证了高可用。
原文链接:https://juejin.cn/post/7057699861868576799
你真的会用K折交叉吗? 对于K折交叉的思考| 防止K折交叉踩坑
作者碎碎念
本文目的:
对于K折交叉,想必大家都知道是什么原理。但是在具体实践中让你写的时候,你可能就会突然疑惑:“咦?道理我都懂,可是这个玩意儿到底怎么用。”
本文就是为了探讨一下什么时候 怎么用 K折交叉验证。
K折交叉(k-fold cross validation)
提到K折交叉,我想大部分人都了解其原理了。但是在这里还是先讲一下什么是K折交叉,防止有初学者是进来看什么是K折交叉的。
简言之,就是将数据随机分为K份,使用其中的K-1份依次进行训练,使用剩下的1份作为测试集,比较常见的有五折交叉、十折交叉。
但是实际写代码的时候遇到了问题,现有以下两种K折交叉方法:
方案1 不预先分出测试集
就是我们看书看博客最常见的说法。
- 将数据随机均分k份。
- 使用其中1份做测试集,剩余k-1份做训练集。
- 通过 k 次训练后,我们得到了 k 个不同的模型。
下图是一个五折交叉的例子:
数据量超级少,精度根本提不到85%。到最后以至于我觉得我的2折交叉方法是错的。
方案2 提前分出测试集
- 将数据集分为训练集和测试集
- 将训练集分为 k 份
- 每次使用 k 份中的 1 份作为验证集,其他k-1份作为训练集
- 通过 k 次训练后,我们得到了 k 个不同的模型
- 从中挑选效果最好的超参数
- 使用最好的超参数模型,然后将 k 份数据全部作为训练集重新训练模型,得到最终模型
- 使用测试集测试最终的效果
以下也是五折交叉的例子:
分析
看到这里是不是突然开始迷惑了?那我到底该用哪一种?
我们来分析一下:
- 方案二,预先划分出测试集,训练之后也得到五个模型,但是取出其中较好的一个,测试集之外的所有数据合起来对其二次训练,训练之后作为最终的模型,并使用测试集评价其效果。
- 方案一,不提前留出测试集,直接所有数据放入模型中一边训练一边测试。这样我们最终会获得5个不同的模型,其之间的效果也会存在差异。
所以这五个模型,你最后要选哪个作为最终方案?
答案是选不出来,因为你没有单独的测试集,五个模型的数据不用,你无法最终验证究竟哪个模型的实际效果更好。
那你可以说:那我也和方案2一样,选出5个中看起来最好的那个模型的参数,然后把所有的数据塞回去重新训练……
你清醒一点,你一开始就没划分测试集,所以你不能把所有的数据再组合起来塞回去训练。因为训练完了你也没测试集看你训练的结果。
那你又说:得到五个模型之后,我再把数据集划分出来,只取所有数据中的一部分作为训练集,剩下一部分测评模型。
清醒一点啊!!你怎么敢的!这属于学术作弊!!!你那五个模型怎么来的?所有数据训练出来的K-1份训练出来的!你这属于用训练集测试集混着用了!
第二波分析:
先说个题外话,我们需要注意数据划分的作用:
- 训练集:训练模型,获得模型参数
模型参数怎么来的?不就是通过反向传播自动调整参数?
- 测试集:测试模型效果
最后测试你训练的模型效果如何。
- 验证集:调整模型超参数
训练过程中,想知道模型设计的好不好,那我们直接使用测试集测试吗?如果你有全部的数据,你确实可以这么做。但是有时候你可能得不到测试集数据,所以你怎么调参?你就需要自己划分出来一个验证集,检验模型性能。
换句话说就是在训练过程中手动调参,调整模型的超参数。
现在有两个模型放在你面前:
- 使用训练集训练,使用测试集测试,效果不好再回去调一调模型超参数。
- 使用训练集训练,使用验证集测试,效果不好回去调一调,调好之后使用测试集测试。
如果上述两个模型最终的测试效果是一样的,现在让你选一个模型,你觉得哪个好?我觉得,直觉上第二个模型的泛化性可能会更好。
因为第二个模型是在完全陌生的数据上进行测试,达到了某个效果。
而第一个模型是在对应的测试集上进行调参得到的最终效果,他的“好”可能仅限于那块测试集的数据,在其他数据上效果不一定比得过第二个模型。
现在回到我们的K折交叉。
方案1中只划分了训练集和测试集,如果你要调参,直接使用测试集调。
方案2中划分了训练集、验证集、测试集,你调参用验证集调,测试集仅作为最终模型测试。
那现在我们就明白了:
- 方案1中:使用测试集调整超参数的话,我们是尽力找到一个超参数能让所有的K-1个模型表现都更好一点,是为了找到比较好的一组超参数。
- 方案2中:使用验证集调整超参数,选出五个模型中看起来最好的,再使用训练集之外的所有数据再训练,最终使用测试集测试效果,这是为了选出一个最终可用的模型。
那我们就可以得出结论了。
所以什么时候用哪种?
方案1 不预先分出测试集:适用于评价模型效果,但是你没办法选出一个具体参数的模型。
就是当你说:我这个模型好!
好在哪里?
我进行K折交叉!出来的五个模型在我设计的超参数之下准确率都不错,所以我这个模型设计的挺好。
那让我用用你这个模型,什么参数下效果最好?
那我就不知道了,选不出来。
方案2 提前留出测试:适用于选择合适的模型。
我需要最终得到一个模型,你必须得要一个具体的模型,不仅有超参数,还要有一组能让模型表现“最好”的参数。这时候你就需要用方案2。
作者碎碎念,本文的写作初衷
月初时候写大作业,要求使用2折交叉验证,
起初我用的方案1,就是提前分出来测试集。然后我闲着没事和师姐交流了一下,师姐说:
???我突然就开始怀疑人生,是我做错了吗?
然后我开始查资料,越查越迷惑。直到最后师哥给我解答了疑惑:
以上是关于会用eureka?你了解原理吗?的主要内容,如果未能解决你的问题,请参考以下文章