> 场景是这样的:
> > 由于 服务注册及发现中心(Eureka),其自身势必有个集群,
那么 > 服务实例注册信息(例:多个Client端注册到不同的Server注册中心),既然形成一个集群里如何保存一致性?
首先了解下 CAP原则说的什么 话不多说,反正都是理解性的东西。 说下面👇的: 三个原则性上 ,
Eureka 只选择里 A原则(一致性(Consistency))
强一致性 VS 最终一致性 区别自己理解去吧。说不清楚的东西。
下面直接说: Per to Per 对等模式:
1、副本之间不分主从,任何副本都可以接收写操作,然后副本之间进行数据更新。
2、不存在写操作的压力瓶颈,另外一个问题就是 副本之间同步数据更新及冲突问题 ?
接下来我分别从 EurekaClient端(客户端) 及EurekaServer端(服务端)
两个角度阐述/分析,Eureka 到底怎么做的它 ?
(1)客户端 Client端一般通过如下配置 Eureka server的peer节点:
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8666/eureka,http://127.0.0.1:8777/eureka .... 等多个
说明:
1、 实际代码里面做了对 PreferSameZoneEureka(优先相同的配置列下的服务注册中心)的支持,
2、如果没有找到则默认使用,defaultZone 配置中的。
3、客户端中使用 QuarantineSet(隔离设置) 维护列一个不可用的 Eureka Server列表;
4、进行请求时,优先从可用列表中进行选择请求,失败了切换下一个,重试次数默认3次。
5、另外为了防止每个Client端都按配置文件指定的顺序;
7、进行请求造成 S节点请求分布不均衡的情况,C端哟股恶定时任务(默认5分钟执行一次),来刷新并随机化Eureka Server列表。
(2)服务端
Eureka Server本身依赖了Eureka Client端,也就是每个Eureka Server是作为其它 Eureka Server 的Client。
在单个S端启动是,会有个SyncUp操作,这样S端中包括C端,也即是S端请求被C端,相互注册发现,相互复制peer节点,同步形成集群。
相互节点复制请求中,被注册的 S端 复制操作使用的是 HEADEER_REPLICSTION http header请求操作与普通应用请求操作区分开处理。
Eureka 采用 如下两个方式来解决——————数据复制的冲突问题?
- .lastDirtyTimestamp (最后脏数据时间戳)标识 ---- 字段对比
1-1. 首先SyncWthenTimsetampDiffers配置(默认是开启的),
1-2. 当lastDirtyTimestamp字段不为空的时候
1-3.进行比较:
== lastDirtyTimestamp值 大于 > S端本地实例的该字段值时,
则标识 S端之间的数据出现冲突,会返回404,要实例重新进行Register(注册)操作。
则反,如果是peer节点的复制请求,则表示数据出现冲突,
返回409给peer节点,要求其同步自己最新的数据消息。==
== peer节点之间的相互复制不能保证所有操作都成功,因此还需要heartbeat(心跳节拍) 也就是renewLease(更新续约)操作来进行数据的最终修复。==
- heartbeat(心跳节拍)
- Eureka 并没有直接采用版本号属性,而是上面👆两种方式。
- Self preservation(自身保全) 设计:
-
C端与S端之间有个租约,C端要定时发送心跳来维持这个租约,表示自己存活着。
Eureka通过当前注册的实例数,去计算每分钟应用实例接收的心跳数,
接收到的续约次数小雨等于指定的阀值时,则关闭租约失效剔除,
禁止定时任务剔除失效的实例,从而保护注册信息。
Eureka Server 端,为了提升自身REST API接口的性能,提供来两个缓存:
一个是基于 ConcurrentMap(并发Map) 的 ReadOnlyCacheMap(读取单一缓存Map)
一个是基础 Guava Cache(潘石榴缓存) 的 ReadWriteCacheMap(读取写缓存Map)