三、spring cloud eureka(基本概念及架构设计)

一、eureka概述

1、背景

(1)netflix公司与AWS的ELB
  • netflix是世界上最大的流媒体视频网站,其公司的架构师基于AWS云开发的。在AWS中使用的负载均衡器是ELB(Elastic Load Balancing),即弹性负载均衡通过流量分发扩展应用系统对外的服务能力(类似阿里云SLB服务)。理论上是可以通过ELB对内部进行负载均衡的,但是如果这样就会暴露到外网,存在安全性问题;另外ELB是基于传统的代理的负载均衡解决方案,无法直接基于服务元数据信息定义负载均衡算法。也就是说使用ELB有一定的限制,无法根据复杂的生产环境提供更为复杂的负载均衡方案,且存在一定的安全隐患。
(2)eureka诞生
  • netflix鉴于自己的生产环境,设计出了eureka,一方面给内部服务做服务发现,另一方面可以结合ribbon组件提供各种个性化的负载均衡算法。ELB亦是传统的基于代理实现的负载均衡解决方案而Eureka则与之不同,Eureka属于客户端发现模式,客户端负责决定相应服务实例的网络位置,并且对请求实现负载均衡。客户端从一个服务注册服务中查询所有可用服务实例的库,并缓存到本地。
(3)ELB和eureka搭配使用
  • 在生产中如果是使用AWS等云服务,可以结合eureka一起使用(以AWS为例),ELB用来对客户端或者终端设备进行请求负载均衡,而eureka用来对中间层的服务做服务发现,配合其他组件提供负载均衡的能力。


    三、spring cloud eureka(基本概念及架构设计)_第1张图片
    使用eureka作为中间负载均衡和服务发现

2、eureka优势

(1)提供完成的服务注册和服务发现实现
  • 首先是提供了完整的服务注册和服务发现实现,并且也经受住了Netflix自己的生产环境考验,相对使用起来会比较省心。
(2)与spirngcloud无缝集成
  • 我们的项目本身就使用了Spring Cloud和Spring Boot,同时Spring Cloud还有一套非常完善的开源代码来整合Eureka,所以使用起来非常方便。另外,Eureka还支持在我们应用自身的容器中启动,也就是说我们的应用启动完之后,既充当了Eureka的角色,同时也是服务的提供者。这样就极大的提高了服务的可用性
(3)采用AP而非CP
  • eureka是在部署AWS的背景下面设计的,其设计认为,在云端,特别是大规模部署情况下面,失败是不可以避免的,可能是因为eureka自身部署失败或者网络分区等情况导致服务不可用,这些问题是不可以避免的,要解决这个问题就需要eureka在网络分区的时候,还能够正常提供服务,因此eureka选择满足availability这个特性。

在生产实践中,服务注册及发现中保留可用以及过期的数据总比丢失可用的数据好。---peter kelly

  • eureka选择了A也就必须放弃C,也就是说在eureka中采用最终一致性的方式来保证数据的一致性问题,因此实例的注册信息在集群的所有节点之间的数据都不是强一性的,需要客户端能支持负载均衡算法及失败重试等机制。
(4)开源
  • 代码是开源的,所以非常便于我们了解它的实现原理和排查问题。需要的话还可以在上面进行二次开发。

3、eureka和zk作为注册中心比较

三、spring cloud eureka(基本概念及架构设计)_第2张图片
eureka和zk作为注册中心时候的比较
比较项目 zk eureka
设计原则 CP AP
优点 数据强一致 服务高可用
缺点 网络分区会影响 Leader 选举,超过阈值后集群不可用 服务节点间的数据可能不一致; Client-Server 间的数据可能不一致;
使用场景 单机房集群,对数据一致性要求较高 云机房集群,跨越多机房部署;对注册中心服务可用性要求较高

二、eureka架构设计

三、spring cloud eureka(基本概念及架构设计)_第3张图片
eureka架构设计图

1、设计理念

(1)AP由于CP
(2)Peer to Peer设计
  • 一般而言在分布式系统的数据有多个副本之间的复制方式,可以分为主从复制和对等复制

主从复制:Master-Slave模式,一个主副本和多个从副本,所有数据的写操作都是提交到主副本,最后由主副本更新到其他的从副本(常采用异步更新),通常写是整个系统的瓶颈所在。
对等复制:副本之间不分主从,任何的副本都可以接受写数据,然后副本之间进行数据更新。在对等复制中,由于每一个副本都可以进行写操作,各个副本之间的数据同步及冲突处理是一个比较难解决的问题。

  • eureka中的对等复制机制

1、客户端:在客户端中配置相应的服务端的多个peer节点,在客户端实际操作中有如下几点规律;(1)有多个分区时候,优先选择与应用实例所在分区一样的其他服务实例,如果没有的话选择默认是defaultZone(2)客户端会维护一个可用的server列表,请求的时候优先从可用的列表中进行选择,如果请求失败切换到下一个server进行重试,重试次数为3次(3)为了防止客户端请求服务端的节点不均匀现象,客户端有一个定时任务来刷新并随机化eureka server的列表。
2、服务端:server本身依赖于客户端,也就是每一个server是作为其他server的客户端存在。在一个server启动的时候,有一个synvUp操作,通过客户端请求其他的server节点中的一个节点获取注册的应用实例信息,然后复制到其他的peer节点。eureka中采用版本号(lastDirtyTimestamp)和心跳机制(renewLease从新租约方式)的方式来解决数据复制过程中的冲突问题。

(3)Zone和region的设计

  • 使用region来代表一个独立的地理区域,比如us-east-1、us-east-2,、us-west-1等。在每一个region下面还分为多个AvailabilityZone,一个region对应多个AvailabilityZone,不同的region之间相互隔离。默认情况下面资源只是在单个region之间的AvailabilityZone之间进行复制,跨region之间不会进行资源的复制。
  • AvailabilityZone看成是region下面的一个一个机房,各个机房相对独立,主要是为了region的高可用考虑的,一个region下面的机房挂了,还有其他的机房可以使用。
  • 一个AvailabilityZone可以设置多个server实例,他们之间构成peer节点,然后采用peer to peer的复制模式进行数据复制。

(4)self preservation设计

  • 在分布式系统设计中,通常需要对应用实例的存活进行健康检验,这里比较难处理的就是网络偶尔抖动或者短暂不可用而造成的误判。因此eureka设计了self preservation机制。server和client之间有一个租约,client定期发送心跳来维护这个租约,表示心跳还活着,eureka通过当前注册的实例数量,去计算每分钟应用从应用实例接受到的心跳数量,如果近一分钟接受到的租约的次数小于等于指定的阈值,则关闭租约失效剔除,禁止定时任务剔除失效的实例,从而保护注册信息。

2、组件调用关系设计

(1)服务提供者

1、启动后,向注册中心发起 register 请求,注册服务
2、在运行过程中,定时向注册中心发送 renew 心跳,证明“我还活着”。
3、停止服务提供者,向注册中心发起 cancel 请求,清空当前服务注册信息。

(2)服务消费者

1、启动后,从注册中心拉取服务注册信息
2、在运行过程中,定时更新服务注册信息。
3、服务消费者发起远程调用:
a> 服务消费者(北京)会从服务注册信息中选择同机房的服务提供者(北京),发起远程调用。只有同机房的服务提供者挂了才会选择其他机房的服务提供者(青岛)。
b> 服务消费者(天津)因为同机房内没有服务提供者,则会按负载均衡算法选择北京或青岛的服务提供者,发起远程调用。

(3)服务注册中心

1、启动后,从其他节点拉取服务注册信息。
2、运行过程中,定时运行 evict 任务,剔除没有按时 renew 的服务(包括非正常停止和网络故障的服务)。
3、运行过程中,接收到的 register、renew、cancel 请求,都会同步至其他注册中心节点

3、数据存储结构

三、spring cloud eureka(基本概念及架构设计)_第4张图片
eureka数据存储结构图
  • Eureka 的数据存储分了两层:数据存储层和缓存层。

Eureka Client 在拉取服务信息时,先从缓存层获取(相当于 Redis),如果获取不到,先把数据存储层的数据加载到缓存中(相当于 Mysql),再从缓存中获取。值得注意的是,数据存储层的数据结构是服务信息,而缓存中保存的是经过处理加工过的、可以直接传输到 Eureka Client 的数据结构。

(1)数据存储层

第一层的 key 是spring.application.name,value 是第二层 ConcurrentHashMap;
第二层 ConcurrentHashMap 的 key 是服务的 InstanceId,value 是 Lease 对象;
Lease 对象包含了服务详情和服务治理相关的属性。

  • 更新一级缓存:

Eureka Server 内置了一个 TimerTask,定时将二级缓存中的数据同步到一级缓存(这个动作包括了删除和加载)。

(2)二级缓存层

一级缓存:ConcurrentHashMap readOnlyCacheMap,本质上是 HashMap,无过期时间,保存服务信息的对外输出数据结构。
二级缓存:Loading readWriteCacheMap,本质上是 guava 的缓存,包含失效机制,保存服务信息的对外输出数据结构。

  • 二级缓存的更新机制:


    三、spring cloud eureka(基本概念及架构设计)_第5张图片
    eureka二级缓存的更新机制
  • 删除二级缓存:

1、Eureka Client 发送 register、renew 和 cancel 请求并更新 registry 注册表之后,删除二级缓存;2、Eureka Server 自身的 Evict Task 剔除服务后,删除二级缓存;3、二级缓存本身设置了 guava 的失效机制,隔一段时间后自己自动失效;

  • 加载二级缓存:

1、Eureka Client 发送 getRegistry 请求后,如果二级缓存中没有,就触发 guava 的 load,即从 registry 中获取原始服务信息后进行处理加工,再加载到二级缓存中。
2、Eureka Server 更新一级缓存的时候,如果二级缓存没有数据,也会触发 guava 的 load。

  • 重点关注:ResponseCacheImpl类

三、eureka高可用原理分析

  • 前面讲了eureka是基于AWS开发出来的框架,因此eureka天生的支持region和availabilityZone的概念。

1、默认情况下面不同region是相互隔离的,region之间的数据是不会复制的,但是eureka client提供了fetch-remote-regions-registry配置,作用是拉取远程的注册信息到本地
2、availabilityZone,eureka中默认eureka-client-prefer-zone-eureka配置为true,也就是拉取serverUrl时候,默认选取和应用实例同一个zone的eureka server列表。

1、客户端高可用原理

(1)在client启动之前,如果没有eureka server,则通过配置eureka.client.back-registry-impl从备份的registry读取关键服务的信息。
(2)在client启动后,如果运行时候server全部挂掉了,本地内存有localRegion之前获取的数据。
(3)如果是server部分挂了。如果预计恢复时间比较长,可以人工介入,通过配置中心人工摘除服务(但是基本不用这样做)。在client中会维护一份不可用的server列表,一旦心跳时候失败,当该列表的大小超过指定的阈值时候就会进行重新清空,重新清空后,client会进行重试(默认3次)

2、服务端高可用原理

  • 服务端采用peer to peer的架构模式,原则上就是高可用的。同时服务端还可以通过配置remoteRegionUrlsWithName来支持拉取远程的region实例,如果当前的region挂了,会自动fallback到远程的region获取数据
  • 同时服务端采用renew租约和定时心跳的方式保护注册信息(self preservation机制)

参考:
微服务注册中心 Eureka 架构深入解读
重新定义springcloud
深度剖析服务发现组件Netflix Eureka
其他资料

你可能感兴趣的:(三、spring cloud eureka(基本概念及架构设计))