eureka去中心化
① 86 SpringCloud解决分布式事务
1,分布式事务产生的背景;
分情况而定。
1,在单体项目中,多个不同的业务逻辑都是在同一个数据源中心实现事务管理,是不存在分布式事务的问题。因为在同一个数据源的情况下都是采用事务管理器,相当于每个事务管理器对应一个数据源。
2,在单体项目中,有多个不同的数据源,每个数据源中都有自己独立的事务管理器,互不影响,那么这时候也会存在多数据源事务管理:解决方案jta+Atomikos
3,在分布式/微服务架构中。每个服务都有自己的本地的事务。每个服务本地事务互不影响,那么这时候也会存在分布式事务的问题。
分布式事务产生的背景:订单服务调用派单服务接口成功之后,可能会引发错误。
2pc3pc思想,实际上都是解决我们在分布式系统中,每个节点保证数据一致性问题。
事务的定义。
对我们业务逻辑可以实现提交或者是回滚,保证数据一致性的情况。所以,要么提交,要么回滚。
原子性a 要么提交 要么回滚。
一致性 c
持久性d 事务一旦提交或者回滚后,不会再对该结果有任何的影响。
Base 与 cap理论。
1,cap定律
这个定理的内容是指的是在一个分布式系统中,Consistency(一致性),Availability(可用性),Partition tolerance(分区容错性),二者不可兼容。
1,一致性(C)
在分布式系统中的所有数据备份,是在同一时刻是否同样的值,(等同于所有节点访问同一份最新的数据副本)
2,可用性 A
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求(对数据更新具有高可用性)
3,分区容错性(p) 形成脑裂问题:
以实际效果而言,分区相当于对通信的时限要求,系统如果不能再时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
4,总结下
以上可以知道分区容错性(P)主要代表网络波动产生的错误,这是不可以避免的,且这三个模式不可以兼得,所以目前就2种模式: cp和Ap模式。
其中cp表示遵循一致性的原则,但不能保证高可用性,其中zookeeper作为注册中心就是采用cp模式,因为zookeeper有过半节点不可以的话整个zookeeper将不可用。
AP表示遵循于可用性原则,例如Eureka作为注册中心用的是AP模式,因为其为去中心化,采用你中有我我中有你的相互注册方式,只要集群中有一个节点可以使用,整个eureka服务就是可用的,但可能会出现短暂的数据不一致问题。
Ap保证可用性:但是不能保证每个副本数据数据一致性,
cp保证数据一致性;如果有过半的zk节点宕机的情况下,不能保证可用性,但是必须保证每个副本节点之间数据一致性,比如zk。
Base理论:
Base是 Basically Available(基本可用),Softstate(软状态)和Eventually consistent(最终一致性)三个短语的缩写。Base理论是对CAP定理逐步演化而来的,base理论核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式达到最终一致性。
1基本可用性;
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性,注意:这绝不等于系统不可用。
比如: 响应时间的损失,正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能顺利完成每一笔订单,但是在一些介入大促销购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能被引导在一个降级页面。
2,软状态。
软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,既允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
3,最终一致性
最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态,因此,最终一致性的本质需要系统保证数据能够达成一致,而不需要时时保证系统数据的强一致性。
2pc 与3pC
通过2pc和3pc 思想可以实现保证每个节点的数据一致性问题。
目前主流分布式解决框架
1,单体项目多数据源,可以jta+Atomilos;
2,基于Rabbitmq的形式解决 最终一致性思想;
3,基于Rocketmq解决分布式事务 ,采用事务消息。
4,lcn采用lcn模式,假关闭连接
5,Alibaba的seata 背景强大,已经成为了主流。
以上适合于微服务架构中,不适合于和外部接口保证分布式事务问题。
6,跨语言的方式实现解决分布式事务问题。类似于支付宝回调方式。
2阶段提交协议基本概念。
2阶段提交协议基本概念:
俩阶段提交协议可以理解为2pc,也就是分为参与者和协调者,协调者会通过2次阶段实现数据最终一致性的
2pc和3pc 的区别就是解决参与者超时问题和多加了一层询问。保证了数据传输的可靠性。
简单的回顾下lcn解决分布式事务。
http://www.txlcn.org/zh-cn/ LCN并不生产事务,LCN只是本地事务的协调工
现在官网已经不维护呢,可以参考:GitEE
https://gitee.com/wangliang1991/tx-lcn?_from=gitee_search
默认密码为:codingapi
lcn基本实现的原理:
1,发起方与参与方都与我们的lcn保持长连接;
2,发起方调用接口前,先向lcn管理器中申请一个全局的事务分组id;
3,发起方调用接口的时候在请求头里传递事务分组id.
4,参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前事务,
5,发起方调用完接口后,如果出现异常的情况下,在通知事务协调者回滚事务,这时候事务协调则告诉给参与者回滚当前的事务。
lcn 解决分布式事务的原理:
角色划分
1,全局事务协调者(组长);
2,发起方---调用接口者;
3,参与方---被别人调用接口
订单(发起方)调用派单(参与方)
1.发起方和参与方都会与我们的全局事务协调者保持长连接;
整合和源码解读
spring-boot 2.1.6.RELEASE+spring-cloud Greenwich.RELEASE +seata 1.4
pom如下:
file.conf
registry.conf:
yml配置:
添加 DataSourceConfiguration
其他模块参照此模块配置,
seata的registry.conf 和file.conf配置和项目配置一致。
添加全局事务:
https://gitee.com/lttwj/wj1/tree/master/seata/springcloud-seata
1,如何学会分析框架的源码?思想有哪些?
A: spring入口角度分析 springbean 生命周期ioc容器底层原理。
B. 报错日志法
2,seata 底层如何解决分布式事务的?
3,seata 如何生成全局xid
4,Seata如何生成前置和后置镜像。
5,seata 如何传递xid的
6, Seata 如何实现逆向回滚
7,如果协调者宕机了,参与事务是回滚还是提交
8,如果协调者宕机发起方没有通知协调者到底是提交还是回滚?
② Nacos对比Zookeeper、Eureka之间的区别
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
一致性(C):在分布式系统中,如果服务器集群,每个节点在同时刻访问必须要保持数据的一致性。
可用性(A):集群节点中,部分节点出现故障后任然可以使用 (高可用)
分区容错性(P):在分布式系统中网络会存在脑裂的问题,部分Server与整个集群失去节点联系,无法组成一个群体。
只有在CP和AP选择一个平衡点
CP情况下:虽然我们服务不通用,但是必须要保证数据的一致性。
AP情况下:可以短暂保证数据不一致性,但是最终可以一致性,不管怎么样,要能够保证我们的服务可用
相同点:三者都可以实现分布式注册中心框架
不同点:
Zookeeper采用CP保证数据的一致性的问题,原理采用(ZAP原子广播协议),当我们ZK领导者因为某种情况下部分节点出现了故障,会自动重新实现选举新的领导角色,整个选举的过程中为了保证数据一致性的问题,客户端暂时无法使用我们的Zookeeper,那么这以为着整个微服务无法实现通讯。
注意:可运行的节点必须满足过半机制,整个zk采用使用。
Eureka采用AP设计思想实现分布式注册中心,完全去中心化、每个节点都是相等,采用你中有我、我中有你相互注册设计思想, 只要最后有一台Eureka节点存在整个微服务就可以实现通讯。
中心化:必须围绕一个领导角色作为核心,选举为领导和跟随者角色
去中心化:每个角色都是均等
Nacos从1.0版本选择Ap和CP混合形式实现注册中心,默认情况下采用Ap,CP则采用Raft协议实现保持数据的一致性。
如果选择为Ap模式,注册服务的实例仅支持临时模式,在网络分区的的情况允许注册服务实例
选择CP模式可以支持注册服务的实例为持久模式,在网络分区的产生了抖动情况下不允许注册服务实例。
必须要求读取接口的地址保证强一致性的问题,可以采用cp模式, 一般情况下采用ap就可以了
Zookeeper基于ZAP协议实现保持每个节点的数据同步,中心化思想集群模式,分为领导和跟随者的角色
在Raft协议中分为的角色
1.状态:分为三种 跟随者、竞选者、领导
2.大多数: >n/2+1
3.任期:每次选举一个新的领导角色 任期都会增加。
默认情况下选举的过程:
核心的设计原理其实就是靠的 谁超时时间最短谁就有非常大的概率为领导角色。
疑问:是否可能会产生两个同时的竞选者呢,同时实现拉票呢?
注意当我们的集群节点总数,如果是奇数情况下 就算遇到了该问题也不用担心。
当我们的节点是为偶数的情况下,可能会存在该问题,如果两个竞选者获取的票数相等的情况下,开始重置竞选的超时时间,一直到谁的票数最多谁就为领导。
本文参考蚂蚁课堂: http://www.mayikt.com/#
③ 26 eureka问题汇总
一 Eureka 服务器端服务剔除
1,Eureka 服务保护机制是如何实现的
Eureka是在Java语言上,基于Restful API开发的服务注册与发现组件,由Netflix开源。Eureka遵循AP原则。目前Eureka仅开源到1.X版本,2.X版本已经宣布闭源。
Eureka采用的是Server/Client的模式进行设计:
Server扮演了服务注册中心的角色,为Client提供服务注册和发现的功能,维护着注册到自身的Client的相关信息,同时提供接口给Client获取到注册表中其他服务的信息。
Client将有关自己的服务的信息通过一定的方式登记到Server上,并在正常范围内维护自己信息的一致性,方便其他服务发现自己,同时可以通过Server获取到自己的依赖的其他服务信息,从而完成服务调用。
Server不进行选举,没有Leader,是一种去中心化的架构,节点都是对等的,通过相互注册提高可用性,通过数据拷贝的方式实现数据的最终一致性。
在集群环境中,如果某台Server节点宕机,Client的请求会自动切换到新的Server节点上,当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中。
自我保护机制
默认情况下,如果Server在一定时间内没有接收到某个服务实例的心跳(默认周期为30秒),Server将会注销该实例(默认为90秒)。如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,启动自我保护机制:
Eureka不再从注册表中移除因为长时间没有收到心跳而过期的服务;
Eureka仍然能够接受新服务注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用);
当网络稳定时,当前实例新注册的信息会被同步到其它节点中;
自我保护机制是Eureka遵循AP原则、保证可用性的关键,只要有一台Server还在就能对外提供服务,但是不保证强一致性,Server内部数据可能不是最新的。
————————————————
2,为什么有人说Eureka服务保护是累赘
因为Eureka的高可用性选择,所以设计了一个自我保护机制,保护那些因为网络分区问题影响的微服务不会移除。但是也可能保护了真正出现了问题的微服务。这个时候,其他的微服务调用这个服务时,可能就会得到一个错误的结果,这种情况只能在调用端自行解决,比如通过Hystrix进行隔离熔断。
3,Eureka 集群环境如何搭建
4,EurekaApp模式如何同步的数据
5,Eureka集群获取宕机后的怎么办
ureka-Server 高可用集群 关于宕机后主动踢出该节点
6,开启了服务保护机制,调用了宕机地址怎么办?
Ap模式: 核心 主要保证高可用:
没有保证集群每个节点数据一致性问题
CP模式 核心: 主要保证每台节点数据一致性,有可能会发生导致集群环境不可用
Eureka ap模式
④ 服务治理选型、Eureka、Consul 的区别
CAP定理:指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可同时获得。
解释CAP理论: 就是说在分布式存储系统中,要满足P,就是允许网络通信可能失败,那么在多个副本之间的同步就可能存在失败,那么某个副本就可能存在过期的数据,只能同时满足两点既AP或者CP,既:我们只能在一致性和可用性之间进行权衡((A)和(C)互斥)。
使用场景,注册中心选择:
Consul :CP设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举行的leader,或者半数以上节点不可用,则无法提供服务,因此可用性没法满足
Eureka:AP原则,无主从节点,一个节点挂了,自动切换其他节点可以使用,去中心化
结论:分布式系统中P,肯定要满足,所以只能在CA中二选一
没有最好的选择,最好的选择是根据业务场景来进行架构设计
如果要求一致性,则选择Consul,如金融行业
如果要去可用性,则Eureka,如电商系统
最大的区别是Eureka保证AP, Consul为CP。
服务注册稍慢,根据raft协议当Leader挂掉时,重新选举期间整个consul不可用,这里可以加入重试机制,在一定时间没有收到 Leader 的数据已接收确认后进行一定次数的重试,并再次向新的 Leader 发送数据来确保业务的流畅性。
服务注册更快,保证了每个节点都可用,但是不保证每个节点的数据一致。如此保证了可用性。
⑤ 90 SpringCloud 解决分布式事务--lcn解决分布式事务
1,分布式事务产生的背景。
分情况而定
1, 在单体的项目中,多个不同的业务逻辑都是在同一个数据源中实现事务管理,是不存在分布式事务的问题,因为同一个数据源的情况都是采用事务管理器,相当于每个事务管理器对应一个数据源。
[图片上传失败...(image-810669-1618491127348)]
2,在单体的项目中,有多个不同的数据源,每个数据源都有自己独立的事务管理器,互不影响,那么这时候也会存在多数据源事务管理: 解决方案 jta+Atomikos
[图片上传失败...(image-7df061-1618491220423)]
3,在分布式/微服务架构中,每个服务都有自己的本地事务,每个服务本地事务互不影响,那么这时候也会存在分布式事务的问题。
事务的定义:
对我们的业务逻辑可以实现提交或者回滚,保证数据的一致性的情况。
所以要么提交,要么回滚
原子性a 要么提交 要么回滚
一致性c
隔离性i 多个事务在一起执行的时候,互不影响;
持久性d 事务一旦提交或者回滚后,不会在对该结果有任何影响
2,传统分布式事务解决方案
3,2PC/3PC协议使用场景。
4,LCN为什么不更新了?那些思想值得学习、
5,分布式事务解决方案有哪些?
6,强一致性/最终一致性区别。
7,LCn深度源码解读。
1 CAP定律和BASE理论
1.1 CAP定律#
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
(一)一致性(C)
在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
(二)可用性(A)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
(三)分区容错性(P) 形成脑裂问题
以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
https://ke..com/item/%E5%AE%B9%E9%94%99%E7%8E%87/9967698?fr=aladdin
(四)总结一下
以上可以知道分区容错性(P)主要代表网络波动产生的错误,这是不可避免的,且这个三个模式不可兼得,所以目前就只有两种模式:CP和AP模式。
其中CP表示遵循一致性原则,但不能保证高可用性,其中zookeeper作为注册中心就是采用CP模式,因为zookeeper有过半节点不可以的话整个zookeeper将不可用。
AP表示遵循于可用性原则,例如Eureka作为注册中心用的是AP模式,因为其为去中心化,采用你中有我我中有你的相互注册方式,只要集群中有一个节点可以使用,整个eureka服务就是可用的,但可能会出现短暂的数据不一致问题。
AP保证可用性:但是不能保证每个副本数据数据一致性;
CP保证数据一致性:如果有过半的zk节点宕机的情况下,不能保证可用性,但是必须保证每个副本节点之间数据一致性, 比如ZK;
BASE是Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
(一)基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性,注意,这绝不等价于系统不可用。
比如:响应时间上的损失。正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了1~2秒。
系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。
(二)软状态
软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性, 即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时 。
(三)最终一致性
最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
目前主流分布式解决框架:
1,单体项目多数据源,可以jta+Atomikos
2,基于RabbitMQ的形式解决,最终一致性的思想。
3,基于RocketMQ解决分布式事务,采用事务消息。
4,LCn采用lcn模式,假关闭连接
5,Alibaba的Seata
6,跨语言的方式实现解决分布式事务问题,类似于支付宝回调。
俩阶段提交协议基本概念:
2阶段提交协议可以理解为2pc,也就是分为参与者和协调者,协调者会通过2次阶段实现数据最终一致性。
2pc和3pc的区别就是解决参与者超时的问题和多加了一层询问,保证数据的传输可靠性。
http://www.txlcn.org/zh-cn/ LCN并不生产事务,LCN只是本地事务的协调工
现在官网已经不维护呢,可以参考:GitEE
https://gitee.com/wangliang1991/tx-lcn?_from=gitee_search
默认密码为:codingapi
lcn基本实现处理:
1,发起方与参与方都与我们的lcn管理器一直保持长连接;
2,发起方在调用接口前,先向lcn管理器中申请一个全局的事务分组id.
3,发起方调用接口的时候在请求头中传递事务分组id
,4参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚事务‘
5,发起方调用完接口后,如果出现异常的情况下,在通知给事务回滚事务,这时候事务协调则告诉参与方回滚当前的事务。
lcn解决分布式事务的原理:
角色划分:
1,全局事务协调者(组长);
2,发起方--调用接口者
3,参与方--被别人调用接口。
订单(发起方)调用派单(参与方)
1.发起方和参与方都会与我们的全局事务协调者保持长连接;
SpringBoot整合lcn5.0
Maven依赖
相关配置
参与方获取全局id
1.SpringTracingApplier
拦截器 获取feign客户端请求头中的参数全局事务分组id,缓存到threadlocal中。
⑥ zookeeper和eureka的区别
zookeeper和eureka的区别:
CAP 原则又称 CAP 定理,1998年,加州大学的计算机科学家 Eric Brewer 提出的,指的是在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得(我们常说的鱼和熊掌不可兼得)。CAP 原则也是 NoSQL 数据库的基石。
1、一致性(Consistency,C):
在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)。
2、可用性(Availability,A):
在一个分布式系统的集群中一部分节点故障后,该集群是否还能够正常响应客户端的读写请求。(对数据更新具备高可用性)。
3、分区容错性(Partition tolerance,P):
当一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有注册列表信息,并完成初始化。Eureka Server 通过 getEurekaServiceUrls方法获取所有的节点,并且会通过心跳契约的方式定期更新。
默认情况下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳,Eureka Server 将会注销该实例。当 Eureka Server 节点在短时间内丢失过多的心跳时,那么这个节点就会进入自我保护模式。
Apache Zookeeper -> CP
与 Eureka 有所不同,Apache Zookeeper 在设计时就紧遵CP原则,即任何时候对Zookeeper 的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是 Zookeeper 不能保证每次服务请求都是可达的。
从 Zookeeper 的实际应用情况来看,在使用 Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用,那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性。
当然,在大多数分布式环境中,尤其是涉及到数据存储的场景,数据一致性应该是首先被保证的,这也是 Zookeeper 设计紧遵CP原则的另一个原因。
但是对于服务发现来说,情况就不太一样了,针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。
因为对于服务消费者来说,能消费才是最重要的,消费者虽然拿到可能不正确的服务实例信息后尝试消费一下,也要胜过因为无法获取实例信息而不去消费,导致系统异常要好
⑦ 闲聊注册中心——ZK、Eureka、Sofa-Registry
最开始服务之间的调用借助的是域名,域名其实是个好东西,使用起来很方便,但所有调用请求都得走域名解析和负载均衡,相对来说性能就差一点,而且这些夹在中间的零部件会演变成性能瓶颈和潜在的单点风险,后来大家一比较发现还不如直接端到端调用,那么就需要一个东西把调用链的两端连起来,这就是注册中心。
注册中心提供服务的注册发现,用来连接调用链路的 Provider 和 Consumer 这两个端点。一个注册中心得管理好服务的扩缩容、故障转移、流量分配这类的核心功能,自身同样需要高可用,妥善解决跨地域部署情况下注册中心节点之间的数据一致性,因此我更倾向于认为注册中心是一个偏向体系化的产品,它的价值依赖于与之相匹配的服务规模和治理体系,它的思想虽然产生得很早,但是规模化地落地并不容易,偏小的服务规模本身对于注册中心的依赖并不明显,实现的手段也没有定式;大型服务又会对注册中心的定位、功能提出更苛刻的需求。
究竟是选择强一致性还是高可用性,当下的主流技术选型倾向于后者,但这并不是说明 CP 组件没有存在的意义,而是 AP 组件更契合互联网对于注册中心的定位。
互联网系统高可用永远是摆在首位的东西,因为系统不可用的时间通常跟财产损失直接挂钩。服务列表在短时间少了一两个节点、多了一两个节点,这点流量倾斜对于大多数服务来说感知并不明显,只需要注册中心在某个短暂的时间窗口内重新达到一致性的状态就可以,注册中心不应该在运行时影响到处于正常调用的两个端点之间的连通性。
CP 的代表就是 zookeeper ,至今 zookeeper 也是非常流行的用于注册中心的组件,这在一定程度上要感谢 bbo 。 bbo 在 zookeeper 中是用一个树形结构的两个节点,分别维护服务的 Provider 和 Comsumer 的,列表注册在这两个节点下面,服务的健康检查依赖 zookeeper 提供的临时节点特性,实际上跟 session 的生命周期绑定在一起,但临时节点的问题就是数据易失,一旦集群故障节点重启丢失服务列表,可能造成服务大面积瘫痪,电商新贵 PDD 就曾经出现过这个问题。
CP 最关键的问题在于无法支持机房容灾,例如 ABC 三个机房,机房 C 和其他两个机房产生了网络隔离,部署在机房 C 的 zookeeper 节点是无法提供写入的,这意味着机房 C 部署的 Provider 不能扩缩容、不能重启,最好在故障期间一直保持原样,否则 Provider 任何操作都会是高危的,会直接影响到部署在机房 C 的 Comsumer 。
顺带说一句,我认为 zookeeper 真挺好的,它本身的定位就是个分布式协调服务,并不是专门为注册中心设计的,你不能拿评价注册中心的眼光去评价它,你要的功能 zookeeper 基本上都有,借助 Curator 拿来就可以用,提供了 election ,提供了 ZAB , TPS 低了点(其实也可以了)但是也满足大部分服务规模。
Eureka —— 奈飞的网红组件, AP 注册中心的代表。 Eureka 1.x 今天回头看来是个很牵强的实现,因为它的架构从诞生之日起,就意味着将来数据规模增长之后大概率会出问题,集群整体可伸缩性很低,每扩容一台 Eureka 节点意味着整体点对点之间需要多一份数据流,而这种 Peer 点对点机制的数据流很容易打满网卡,造成服务端压力。根据公开的资料, Eureka 在实例规模五千左右时就会出现明显的性能瓶颈,甚至是服务不可用的情况。
但是从另一个方面来说, Eureka 的架构清晰、运维部署都很方便,而且 Eureka 作为 SpringCloud 推荐的注册中心实现,国内用户数目也相当可观,可见在服务规模恰当的情况下其性能并没有问题,从携程的分享资料也可以看出,其内部的注册中心也是类似于 Eureka 的实现,可见没有绝对完美的架构设计,适合自己、满足业务需求才是最主要的。
Eureka 服务端多节点架构其实有点去中心化的意思,有意保持了每个节点的无状态特性,但是代价就是每个节点都持有全量数据,新增的数据可以往任意一个节点写入,然后由这个节点向其他节点广播,最终达到一致性。
数据都没有持久化,仅保存在内存中,带来了更好的读写性能、更短的响应时间,但是无法处理数据瓶颈,大节点扩容造成的数据同步存在打满网卡的风险,这点跟 redis 集群很像。客户端 30s 定期上报心跳、客户端缓存服务列表这些都没什么好谈的, Eureka 有个很有意思的点是,它的集群节点实现了一个自我保护机制,用来预测到底是集群出问题还是客户端出问题,实现很简单但是思想挺实用的。
Eureka 2.0 的设计文档上体现了读写分离集群的思想,本质上是为了提升集群性能和容量,但是非常遗憾,目前 2.0 的状态是 Discontinued ,短时间应该不会有成熟的产品出现。
虽然没有 Eureka 2.0 ,但是可以从蚂蚁开源的 Sofa-Registry 中了解类似思想的实现,Sofa-Registry 脱胎于阿里的 ConfigServer ,从公开的资料显示,国内阿里应该是最早做注册中心读写分离实践的。
这种架构带来的直接好处就是可以支持海量数据,第一层的 session 集群可以无限水平扩展,彼此之间完全不需要通信, session 集群在内存中维护了注册中心需要的一切拓扑关系,客户端仅仅连接一部分 session 集群中的机器,如果某台 session 机器挂了客户端会选择另一台重连;背后的 data 集群则通过分片存储所有的源数据,分片之间通过主从副本保证高可用,再将源数据推送到 session 集群保存下来,供客户端读取。
缺点也很明显,这种架构人力投入、运维成本肯定高于 Eureka 。
这几乎是注册中心不可避免的问题,高可用、机房容灾、网络延迟等都会催生出要求注册中心节点能够跨地域部署,这会引申出另一个问题就是如何做数据同步。
这种情况下已经不可能通过客户端注册或者是集群节点数据流复制来保证异地注册中心集群之间的数据一致,而是会研发单独的数据同步组件,通过跨地域专线实现地域间注册中心的数据同步,如果专线断开,此时各自地域的注册中心依旧可以独立服务于本地域内服务的调用,等到专线恢复,二者的数据继续进行同步合并纠正,最终达到一致性。对这个知识点感兴趣的可以了解下 Nacos-Sync 组件,是 Nacos 项目专门推出的开源数据同步服务。
文章略过了一些注册中心通用的概念,例如数据模型的分层、服务列表本地缓存、健康检查的方式、推拉权衡等,我认为叙述这些细节的意义并不大。
很多时候,理解某个组件我认为最重要的是理清它的架构演进过程,这是宝贵的经验财富,你可以抓住并学习每次架构演进的方向和原因。
⑧ springcloud四个注册中心的比较
springcloud是一个非常优秀的微服务框架,要管理众多的服务,就需要对这些服务进行治理,也就是我们说的 服务治理 , 服务治理 的作用就是在传统的rpc远程调用框架中,管理每个服务与每个服务之间的依赖关系,可以实现服务调用、负载均衡、服务容错、以及服务的注册与发现。
如果微服务之间存在调用依赖,就需要得到目标服务的服务地址,也就是微服务治理的 服务发现 。要完成服务发现,就需要将服务信息存储到某个载体,载体本身即是微服务治理的 服务注册中心 ,而存储到载体的动作即是 服务注册 。
springcloud支持的注册中心有 Eureka 、 Zookeeper 、 Consul 、 Nacos
Spring Cloud Netflix 在设计 Eureka 时就紧遵AP原则,Eureka Server 也可以运行多个实例来构建集群,解决单点问题,但不同于 ZooKeeper 的选举 leader 的过程,Eureka Server 采用的是Peer to Peer 对等通信。这是一种去中心化的架构,无 master/slave 之分,每一个 Peer 都是对等的。在这种架构风格中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。每个节点都可被视为其他节点的副本。
在集群环境中如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点上,当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会在节点间进行复制(replicate To Peer)操作,将请求复制到该 Eureka Server 当前所知的其它所有节点中。
Eureka的集群中,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使得整个注册服务瘫痪
与 Eureka 有所不同,Apache Zookeeper 在设计时就紧遵CP原则,即任何时候对 Zookeeper 的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是 Zookeeper 不能保证每次服务请求都是可达的。从 Zookeeper 的实际应用情况来看,在使用 Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用(例如有三个节点,如果节点一检测到节点三挂了 ,节点二也检测到节点三挂了,那这个节点才算是真的挂了),那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性。
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X)。Consul 内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等),使用起来也较为简单。
Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。
Nacos是阿里开源的,Nacos 支持基于 DNS 和基于 RPC 的服务发现。Nacos除了服务的注册发现之外,还支持动态配置服务。动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。 一句话概括就是Nacos = 注册中心 + 配置中心。
这四个组件虽然都实现了注册中心的功能,但是他们的功能和实现方式都有不同的地方,也各有各的优点,单从注册中心方面来比价四个注册中心(如果不了解 CAP定理 可先阅读下一章节):
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足。
因此在进行分布式架构设计时,必须做出取舍。当前一般是通过分布式缓存中各节点的最终一致性来提高系统的性能,通过使用多节点之间的数据异步复制技术来实现集群化的数据一致性。通常使用类似 memcached 之类的 NOSQL 作为实现手段。虽然 memcached 也可以是分布式集群环境的,但是对于一份数据来说,它总是存储在某一台 memcached 服务器上。如果发生网络故障或是服务器死机,则存储在这台服务器上的所有数据都将不可访问。由于数据是存储在内存中的,重启服务器,将导致数据全部丢失。当然也可以自己实现一套机制,用来在分布式 memcached 之间进行数据的同步和持久化,但是实现难度是非常大的
例如,根据CAP定理将NoSql数据分成了满足CA原则、满足CP原则和满足AP原则的三大类:
⑨ 【知识总结】6.服务注册发现框架比较(Consul/Zookeeper/etcd/Eureka)
服务发现就是服务提供者将自己提供的地址post或者update到服务中介,服务消费者从服务中介那里get自己想要的服务的地址。
但是有两个问题:
第一个问题:如果有一个服务提供者宕机,那么中介的key/value中会有一个不能访问的地址,该怎么办?
心跳机制: 服务提供者需要每隔5秒左右向服务中介汇报存活,服务中介将服务地址和汇报时间记录在zset数据结构的value和score中。服务中介需要每隔10秒左右检查zset数据结构,踢掉汇报时间严重落后的地址。这样就可以保证服务列表中地址的有效性。
第二个问题是服务地址变动时如何通知消费者。有两种解决方案。
第一种是轮询,消费者每隔几秒查询服务列表是否有改变。如果服务地址很多,查询会很慢。这时候可以引入服务版本号机制,给每个服务提供一个版本号,在服务变动时,递增这个版本号。消费者只需要轮询这个版本号的变动即可知道服务列表是否发生了变化。
第二种是采用pubsub。这种方式及时性要明显好于轮询。缺点是每个pubsub都会占用消费者一个线程和一个额外的连接。为了减少对线程和连接的浪费,我们使用单个pubsub广播全局版本号的变动。所谓全局版本号就是任意服务列表发生了变动,这个版本号都会递增。接收到版本变动的消费者再去检查各自的依赖服务列表的版本号是否发生了变动。这种全局版本号也可以用于第一种轮询方案。
CAP理论
CAP理论是分布式架构中重要理论
关于P的理解,我觉得是在整个系统中某个部分,挂掉了,或者宕机了,并不影响整个系统的运作或者说使用,而可用性是,某个系统的某个节点挂了,但是并不影响系统的接受或者发出请求,CAP 不可能都取,只能取其中2个。原因是
(1)如果C是第一需求的话,那么会影响A的性能,因为要数据同步,不然请求结果会有差异,但是数据同步会消耗时间,期间可用性就会降低。
(2)如果A是第一需求,那么只要有一个服务在,就能正常接受请求,但是对与返回结果变不能保证,原因是,在分布式部署的时候,数据一致的过程不可能想切线路那么快。
(3)再如果,同事满足一致性和可用性,那么分区容错就很难保证了,也就是单点,也是分布式的基本核心,好了,明白这些理论,就可以在相应的场景选取服务注册与发现了。
平时经常用到的服务发现的产品进行下特性的对比,首先看下结论:
补充:
(1)运维和开发如果是 Java 更熟,也更多 Java 的应用,那毫无疑问应该用 ZK;如果是搞 Go 的,那么还是 etcd 吧,毕竟有时候遇到问题还是要看源码的。
(2)在创建一百万个或更多键时,etcd可以比Zookeeper或Consul稳定地提供更好的吞吐量和延迟。此外,它实现了这一目标,只有一半的内存,显示出更高的效率。但是,还有一些改进的余地,Zookeeper设法通过etcd提供更好的最小延迟,代价是不可预测的平均延迟。
(3)
一致性协议: etcd 使用 Raft 协议,Zookeeper 使用 ZAB(类PAXOS协议),前者容易理解,方便工程实现;
运维方面:etcd 方便运维,Zookeeper 难以运维;
数据存储:etcd 多版本并发控制(MVCC)数据模型 , 支持查询先前版本的键值对
项目活跃度:etcd 社区与开发活跃,Zookeeper 感觉已经快死了;
API:etcd 提供 HTTP+JSON, gRPC 接口,跨平台跨语言,Zookeeper 需要使用其客户端;
访问安全方面:etcd 支持 HTTPS 访问,Zookeeper 在这方面缺失;
与 Eureka 有所不同,Apache Zookeeper 在设计时就紧遵CP原则,即任何时候对 Zookeeper 的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是 Zookeeper 不能保证每次服务请求都是可达的。
从 Zookeeper 的实际应用情况来看,在使用 Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用(例如有三个节点,如果节点一检测到节点三挂了 ,节点二也检测到节点三挂了,那这个节点才算是真的挂了),那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性。
当然,在大多数分布式环境中,尤其是涉及到数据存储的场景,数据一致性应该是首先被保证的,这也是 Zookeeper 设计紧遵CP原则的另一个原因。
但是对于服务发现来说,情况就不太一样了,针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。
因为对于服务消费者来说,能消费才是最重要的,消费者虽然拿到可能不正确的服务实例信息后尝试消费一下,也要胜过因为无法获取实例信息而不去消费,导致系统异常要好(淘宝的双十一,京东的618就是紧遵AP的最好参照)。
当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30~120s,而且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。
在云部署环境下, 因为网络问题使得zk集群失去master节点是大概率事件,虽然服务能最终恢复,但是漫长的选举事件导致注册长期不可用是不能容忍的。
Spring Cloud Netflix 在设计 Eureka 时就紧遵AP原则。Eureka是在Java语言上,基于Restful Api开发的服务注册与发现组件,由Netflix开源。遗憾的是,目前Eureka仅开源到1.X版本,2.X版本已经宣布闭源。
Eureka Server 也可以运行多个实例来构建集群,解决单点问题,但不同于 ZooKeeper 的选举 leader 的过程,Eureka Server 采用的是Peer to Peer 对等通信。这是一种去中心化的架构,无 master/slave 之分,每一个 Peer 都是对等的。在这种架构风格中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。每个节点都可被视为其他节点的副本。
在集群环境中如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点上,当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会在节点间进行复制(replicate To Peer)操作,将请求复制到该 Eureka Server 当前所知的其它所有节点中。
当一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有注册列表信息,并完成初始化。Eureka Server 通过 getEurekaServiceUrls() 方法获取所有的节点,并且会通过心跳契约的方式定期更新。
默认情况下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳(默认周期为30秒),Eureka Server 将会注销该实例(默认为90秒, eureka.instance.lease-expiration-ration-in-seconds 进行自定义配置)。
当 Eureka Server 节点在短时间内丢失过多的心跳时,那么这个节点就会进入自我保护模式。
Eureka的集群中,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
Eureka不再从注册表中移除因为长时间没有收到心跳而过期的服务;
Eureka仍然能够接受新服务注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用);
当网络稳定时,当前实例新注册的信息会被同步到其它节点中;
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使得整个注册服务瘫痪。
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X)。
Consul采用主从模式的设计,使得集群的数量可以大规模扩展,集群间通过RPC的方式调用(HTTP和DNS)。
Consul 内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等),使用起来也较为简单。
Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。
默认依赖于SDK
Consul本质上属于应用外的注册方式,但可以通过SDK简化注册流程。而服务发现恰好相反,默认依赖于SDK,但可以通过Consul Template(下文会提到)去除SDK依赖。
Consul Template
Consul,默认服务调用者需要依赖Consul SDK来发现服务,这就无法保证对应用的零侵入性。
所幸通过 Consul Template ,可以定时从Consul集群获取最新的服务提供者列表并刷新LB配置(比如nginx的upstream),这样对于服务调用者而言,只需要配置一个统一的服务调用地址即可。
Consul强一致性(C)带来的是:
Eureka保证高可用(A)和最终一致性:
其他方面,eureka就是个servlet程序,跑在servlet容器中; Consul则是go编写而成。
etcd是一个采用http协议的分布式键值对存储系统,因其易用,简单。很多系统都采用或支持etcd作为服务发现的一部分,比如kubernetes。但正事因为其只是一个存储系统,如果想要提供完整的服务发现功能,必须搭配一些第三方的工具。
比如配合etcd、Registrator、confd组合,就能搭建一个非常简单而强大的服务发现框架。但这种搭建操作就稍微麻烦了点,尤其是相对consul来说。所以etcd大部分场景都是被用来做kv存储,比如kubernetes。
etcd 比较多的应用场景是用于服务发现,服务发现 (Service Discovery) 要解决的是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务如何才能找到对方并建立连接。和 Zookeeper 类似,etcd 有很多使用场景,包括:
配置管理
服务注册发现
选主
应用调度
分布式队列
分布式锁
按照官网给出的数据, 在 2CPU,1.8G 内存,SSD 磁盘这样的配置下,单节点的写性能可以达到 16K QPS, 而先写后读也能达到12K QPS。这个性能还是相当可观。
etcd 提供了 etcdctl 命令行工具 和 HTTP API 两种交互方法。etcdctl命令行工具用 go 语言编写,也是对 HTTP API 的封装,日常使用起来也更容易。所以这里我们主要使用 etcdctl 命令行工具演示。
(1)注册中心ZooKeeper、Eureka、Consul 、Nacos对比
https://zhuanlan.hu.com/p/165217227?utm_source=wechat_session
(2)常用的服务发现对比(Consul、zookeeper、etcd、eureka)
https://blog.csdn.net/gaohe7091/article/details/101197107
⑩ 字节三面:到底知不知道什么是Eureka
什么是服务注册?
首先我们来了解下,服务注册、服务发现和服务注册中心的之间的关系。
举个形象的例子,三者之间的关系就好像是供货商,顾客和商店。
首先各地的供货商会将各种商品提供给商店,然后顾客需要商品的时候会去商店购买。
注册中心就好比是这个商店,供货商的动作就是服务注册,商品就是注册的服务。
当部署的服务启动后,会注册到注册中心,消费者需要什么样的服务,就自己去注册中心拉取。
那么到底什么是服务注册,为什么要将服务注册到注册中心呢?
服务注册指的是服务在启动时将服务的信息注册到注册中心中,由注册中心统一对所有的注册的服务进行管理。
现在我们想想,假如你是消费者,你需要买一个商品,你可以去商店,也可以直接去供货商。
但是如果今天你要买很多商品,而且我们并不知道每个商品对应的供应商的地址,那么你就得挨家挨户的去跑供货商购买商品。
是不是就很麻烦了,倘若此时有一家商店,汇总了多家供货商的商品,那你是不是只需要去这一家商店就能购买到你需要的所有的商品了呢?
这样是不是就方便了。
在我们现实开发中,比如我们需要获取用户信息的时候,而此时,我们的用户服务只部署了一个节点,那我们就可以使用IP+端口的形式访问服务。
当此时我们的服务部署了10个节点后,我们可以通过域名访问,通过nginx转发到某一个节点上,访问该节点的服务。
使用过nginx的小伙伴们都知道,每当我们需要新增一个节点的时候,我们就需要去修改nginx的配置文件,一旦服务部署的节点过多,频繁修改配置文件就变成了一件极其麻烦的事情。
这个时候,我们的注册中心,就应该粉墨登场了。
注册中心一登场,我们就尽管部署服务节点,部署完成后,服务启动,服务的信息就会被注册到注册中心,我们就不需要担心是不是又要去修改配置文件了。
什么是服务发现?
服务发现有两种模式:一种是客户端发现模式,一种是服务端发现模式。Eureka采用的是客户端发现模式。
客户端发现模式就好比我是一个土豪顾客,我去了商店,我把所有的商品都买回家,需要的时候在这些商品里面寻找。
因为我是土豪,所以我当然不能忍受商店里有新品上架,而我却没有,所以我每隔一段时间就会商店增量获取最新的商品。
这就是Eureka中的Fetch Registry,抓取注册信息。
Eureka Client 从 Eureka Server 获取注册表信息并在本地缓存。
这里我们注意一下,Eureka Client并不是直接去服务注册表中获取数据,而是从ReadOnly缓存中获取数据。
并且会通过在上一个获取周期和当前获取周期之间获取增量更新,这些信息会定期更新(每30秒更新一次)。
获取的时候可能返回相同的实例。Eureka Client会自动处理重复信息。
因为我的土豪行为,我已经被商店老板记录在它的VVIP名单上了。可惜天有不测风云,我破产了,我再也不能这么土豪了,没办法,我告诉了老板我破产了,老板听了我的话,想都没想,直接从他的VVIP名单上将我的名字给剔除了,社会就是这么现实。
这就是Eureka中的Cancel,取消。
每一个微服务节点关闭时,Eureka Client会向Eureka Server发送一个取消请求。
Eureka Server收到你的取消请求后,就会将你从服务注册表中给剔除。
商店老板是个傲娇的人,她制定了一个规则,如果你是她VVIP名单上的人,你必须每隔一段时间就要去商店采购商品。
一旦你在一段时间内没有来采购,她就觉得你已经没有购买能力,不适合在她的VVIP名单上存在了。
她就会狠心的将你从她的VVIP名单上将我的名字给剔除了。
这就是Eureka中的Renew(更新 / 续借)
Eureka Client 内部具备一个内置的负载均衡器,它使用轮训(round-robin)负载算法。
在服务启动后,每隔一定周期(默认30秒)向Eureka Server发送心跳。
如果Eureka Server在多个心跳周期内(默认90秒)没有收到Eureka Client发送过来的心跳,Eureka Server将会在服务注册表中将该节点剔除。
当然了,服务发现去注册中心拉取的是服务的信息,然后需要从服务信息中获取到服务部署的节点信息,然后通过域名地址访问到该节点的服务。
就好像一家商店,因为空间太小,只是存放了一些商品的微缩模型,模型上写着该商品所属的供货商地址,我们去商店拿到该模型后,看到供货商的地址,然后我们就可以直接去供货商那儿直接购买商品了。
什么是注册中心,注册中心的作用?
注册中心就是一个管理器,各个服务提供者将服务注册到注册中心,由注册中心进行统一的存储和管理。
注册中心同时还有着判断服务是否可用,对于不可用的服务进行剔除的功能。
至于如何判断服务的可用性和如何剔除不可用的服务,后续会有详细的讲解。
什么是 Eureka,有什么作用?
Eureka采用CS架构,它分为两大组件。
一个是Eureka Server,注册中心服务端。
当各个微服务节点启动后,Eureka Server 会存储服务提供者注册上来的服务信息,并且提供二层缓存机制来维护整个注册中心。
另一个是Eureka Client,注册中心客户端。
Eureka Client是一个java客户端,它用来简化和Eureka Server交互。
Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。
因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。
Eureka 架构详解
如下图所示,这是官网提供给我们的Eureka的架构图Eureka 的架构,主要分为 Eureka Server 和 Eureka Client 两部分,Eureka Client 又分为 Applicaton Service 和 Application Client,Applicaton Service 就是服务提供者,Application Client 就是服务消费者。
我们首先会在应用程序中依赖 Eureka Client,项目启动后 Eureka Client 会向 Eureka Server 发送请求,进行注册,并将自己的一些信息发送给 Eureka Server。
注册成功后,每隔一定的时间,Eureka Client 会向 Eureka Server 发送心跳来续约服务,也就是汇报健康状态。如果客户端长时间没有续约,那么 Eureka Server 大约将在 90 秒内从服务器注册表中删除客户端的信息。
Eureka Client 还会定期从 Eureka Server 拉取注册表信息,然后根据负载均衡算法得到一个目标,并发起远程调用,关于负载均衡在后面的课时会详细介绍,也就是 Ribbon 组件。
应用停止时也会通知 Eureka Server 移除相关信息,信息成功移除后,对应的客户端会更新服务的信息,这样就不会调用已经下线的服务了,当然这个会有延迟,有可能会调用到已经失效的服务,所以在客户端会开启失败重试功能来避免这个问题。
Eureka Server 会有多个节点组成一个集群,保证高可用。Eureka Server 没有集成其他第三方存储,而是存储在内存中。
所以 Eureka Server 之间会将注册信息复制到集群中的 Eureka Server 的所有节点。
这样数据才是共享状态,任何的 Eureka Client 都可以在任何一个 Eureka Server 节点查找注册表信息。
Eureka 的工作流程
Eureka 的自我保护机制
什么是自我保护机制
官方定义:自我保护模式正是一种针对网络异常波动时的安全保护措施,使用自我保护模式能使Eureka集群更加健壮稳定的运行。
为什么要开启自我保护机制?
如果Eureka Server在一定时间内(默认90s)(可优化)没有收到某一个服务节点的心跳,Eureka Server将会移除该服务实例。
但是在某些时候,遇到网络分区故障,服务节点实际上是正常存活状态,但是却无法和Eureka Server正常通信,此时如果没有引入自我保护机制,Eureka Server就会将该服务节点剔除。
自我保护模式的工作机制
如果15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka Server就会认为客户端与注册中心发生了网络故障,Eureka Server进入自我保护机制。
自我保护机制的缺点
如果在自我保护机制中,刚好某些服务节点非正常下线,但是Eureka Server并不会剔除该服务节点,服务消费者就会获取到一个无效的服务实例。
解决方案
① :关闭自我保护机制(不推荐)
② :切换请求或断路器,使用负载均衡的方式,设置当一个请求超过多少秒还未得到响应,速度切换请求到下一个注册服务,例如使用Ribbon+Hystrix配置负载均衡和断路器。
Eureka Server 进入自我保护机制后
1、Eureka Server不再从注册表中剔除因为长时间没有和注册中心续约的服务节点
2、Eureka Server仍然能够接受新服务的注册和查询请求,但是不会同步到其他Eureka Server节点上
3、网络正常后,当前Eureka Server节点会将新的服务节点信息同步到其他Eureka Server节点上
如何开启自我保护
通过
eureka.server.enable-self-preservation=true/false来开启或关闭自我保护机制。
其他关键配置:
清理失效服务节点的时间间隔:
eureka.server.evication-interval-timer-in-ms默认60s
续约间隔时间:
eureka.instance.lease-renewal-interval-in-seconds默认30s
续约到期时间:
eureka.instance.lease-expiration-ration-in-seconds默认90s
通过源码窥探Eureka是如何开启自我保护机制的
第一步,我们引入Eureka Server 依赖。
第二步,我们找到eureka-core jar包下的路径为com.netflix.eureka下的registry包
第三步,进入AbstractInstanceRegistry 类,找到evict方法,这个是定期剔除任务的线程最终执行的方法
第四步,我们找到isLeaseExpirationEnabled()方法的实现
第五步,我们注意到
numberOfRenewsPerMinThreshold这个变量很关键,它的含义是每分钟最小的续约次数
在服务注册register和服务下线cancel两个方法中会更新这个变量,更新该变量方法如下:
以上就是Eureka开启自我保护的整个逻辑流程。
解除自我保护机制
1.当服务的网络分区故障解除之后,客户端能够和服务进行交互时,在续约的时候,更新每分钟的续约数,当每分钟的续约数大于85%时,则自动解除。
2.重启服务
Eureka 的健康检查
其实很多框架的健康状态监控都是通过 actuator 来管理健康状态的,并且扩展了 health 端点。
所以说我们只要在项目中集成Actuator,我们就能管理监控项目的健康状态。
Eureka也是一样,我们可以将某些不健康的服务节点的状态告知Eureka Server,然后Eureka Server 会主动让其下线。
这个就是Eureka的健康检查。
如何实现Eureka-Actuator健康检查?
首先我们要在pom中依赖
spring-boot-starter-actuator。
第二步,配置文件中添加
eureka.client.healthcheck.enabled=true 配置
原理分析:
首先在 中根据 eureka.client.healthcheck.enabled 的值来决定是否要装配 EurekaHealthCheckHandler ,然后在 EurekaClientAutoConfiguration 中会注册 HealthCheck ,但我们注册完成后会有调用任务来进行状态的更新,在 com.netflix.discovery.InstanceInfoReplicator.run() 中会进行状态更新。
Eureka 的多级缓存机制
什么是多级缓存机制
Eureka Server 为了避免同时读取内存数据造成的并发冲突问题,采用了多级缓存机制提升服务请求的响应速度。
Eureka Server的缓存是通过一个只读,一个读写缓存来实现的。
一级缓存:concurrentHashMap<key,value>readOnlyCacheMap本质是HashMap,无过期时间,保存数据信息对外输出。
readOnlyCacheMap依赖于定时器的更新,通过与readWriteCacheMap的值做对比,以readWriteCacheMap为准。
responseCacheUpdateIntervalMs:readOnlyCacheMap缓存更新间隔,默认30s
二级缓存:LoaDing<key,value>readWriteCacheMap本质是Guava缓存,包含失效机制,保护数据信息对外输出。
:readWriteCacheMap 缓存过期时间,默认180s。
当服务节点发生注册,下线,过期,状态变更等变化时
1.在内存中更新注册表信息
2.同时过期掉readWriteCacheMap缓存,缓存清除只是会去清除readWriteCacheMap这个缓存, readOnlyCacheMap 只读 缓存并没有更新,也就说当客户端的信息发生变化之后, 只读缓存不是第一时间感知到的。只读缓存的更新只能依赖那个30秒的定时任务来更新。
3.一段时间后(默认30s),后台线程发现readWriteCacheMap缓存为空,于是也将readOnlyCacheMap中的缓存清空
4.当有服务消费者拉取注册表信息时,会调用ClassLoader的load方法,将内存中的注册表信息加载到各级缓存中,并返回注册表信息。
在Eureka Server 中会有两个线程,一个是定时同步两个缓存的数据,默认30s,一个是定时检测心跳故障,默认90s。
服务拉取
1.服务消费者,默认每30s,拉取注册表信息
2.从readOnlyCacheMap中获取信息,如果获取为空
3.从readWriteCacheMap中获取,如果还是为空
4.调用ClassLoader的load方法,将内存中的注册表信息加载到各级缓存中,并返回注册表信息。
Eureka的区域配置
当用户地理分布范围很广的时候,比如公司在上海、杭州、青岛等都有分公司的时候,一般都会有多个机房。
那么对于用户而言,当然是希望调用本地分公司的机房中的微服务应用。
比如:上海用户A,调用OAuth2服务,用户A当然希望调用上海机房里面的微服务应用。如果上海用户A调用杭州机房的OAuth2服务,就增加的延时时间。
所以我们希望一个机房内的服务优先调用同一个机房内的服务,当同一个机房的服务不可用的时候,再去调用其它机房的服务,以达到减少延时的作用。
为此,eureka提供了region和zone两个概念来进行分区,Eureka基于Amazon设计的,所以对于地域的区分也与Amazon一致,Amazon分为多个region,每个region包含多个zone,所以Eureka设计时也是可以设置region与zone,请求时可以优先选择与请求服务在同一个zone的服务。
基本配置
此时无论我们调用多少次,调用的都是shanghai下面的zone1下面的服务。
一般来说我们都会结合Ribbon来实现微服务的负载均衡,而Ribbon内部会有一些专门的负载策略算法,虽然刚刚我们说过会优先请求的是指定region下指定 Zone 区域的服务实例。
但有些时候比如当在Region=shanghai下没有可用的zone,系统会默认加载 DEFAULT_ZONE,或者说或者同区域的服务负载过高...等等,也会自动切换成其他区域的服务。
Eureka的重试机制
由于 Spring Cloud Eureka 实现的服务治理机制强调了 CAP 原理中的 AP,即可用性与可靠性,牺牲了一定的一致性(在极端情况下它宁愿接受故障实例也不要丢掉"健康"实例,如同如我们上面所说的自我保护机制)。
但不论是由于触发了保护机制还是服务剔除的延迟,引起服务调用到这些不正常的服务,调用就会失败,从而导致其它服务不能正常工作!
这显然不是我们愿意看到的,我们还是希望能够增强对这类问题的容错。所以,我们在实现服务调用的时候通常会加入一些重试机制。
从 Camden SR2 版本开始,Spring Cloud 就整合了 Spring Retry 来增强 RestTemplate 的重试能力,对于开发者来说只需通过简单的配置,原来那些通过 RestTemplate 实现的服务访问就会自动根据配置来实现重试策略。
开启Eureka的重试机制很简单,首先我们在pom中引入Spring Retry的依赖:
然后在配置文件中配置
spring.cloud.loadbalancer.retry.enabled参数来控制重试机制的开关,因为 Spring Retry默认是开启的,所以说我们只要引入依赖即可,如果说我们想要关闭的话只需要将 spring.cloud.loadbalancer.retry.enabled设置为false即可。
其实在SpringCloud的架构组件中无论是Fegin,Ribbon,还是Zuul都提供了重试机制,这些暂且不论,后续再讲到具体的组件时再进行具体的分析。
实战 Eureka 注册中心的部署
Eureka Server 项目搭建
1、创建一个 springcloud-eureka-server 的项目,然后在 pom 中增加
spring-cloud-starter-netflix-eureka-server 的依赖。
2.在pom.xml文件中新增
spring-cloud-starter-netflix-eureka-server依赖
3.在启动类
上使用 @EnableEurekaServer 开启 EurekaServer 的自动装配功能。
4.添加配置文件application.properties
5.启动项目,然后访问 http://localhost:8761/ ,可以看到 Eureka 的管理页面,表示 Eureka 启动成功了。
1、创建一个 springcloud-eureka-client 的项目,然后在 pom 中增加
spring-cloud-starter-netflix-eureka-client 的依赖。
2.在启动类
上使用 @EnableEurekaClient 开启 EurekaServer 的自动装配功能。
配置
eureka.client.serviceUrl.defaultZone 的地址,也就是刚刚启动的 Eureka Server 的地址, http://localhost:8761/eureka/ 。
启动客户端,然后刷新刚刚打开的Eureka主页,我们发现服务已经注册成功。
Eureka 注册中心添加密码认证
上面我们看到我们搭建好Eureka Server 后访问 http://localhost:8761/ ,没有登陆就可以直接看到 Eureka 的管理页面。
如果在实际使用中,注册中心地址有公网 IP 的话,必然能直接访问到,这样是不安全的。所以我们需要对 Eureka 进行改造,通过集成 Spring-Security 来进行安全认证,加上权限认证来保证安全性。
首先,在 pom.xml 中引入 Spring-Security 的依赖
然后在 application.properties 中加上认证的配置信息
最后增加Spring Security 配置类
这样我们启动Eureka Server成功后在访问 http://localhost:8761/ ,此时浏览器会提示你输入用户名和密码,输入正确后才能继续访问 Eureka 提供的管理页面。
总结
本章我们主要学习了Eureka相关知识,虽然Eureka已经停更了,但是很多公司还在使用它,而它也足够稳定,它所提供的功能也足够大多数公司使用。所以说现在面试中,Eureka相关题目还是经常出现的。反正学到了就是自己的。
祝愿大家早日成为大牛,有一头乌黑秀发的大牛。