Spring Cloud -Eureka 源码

服务端源码

图1

Spring Cloud -Eureka 源码_第1张图片

Spring Cloud -Eureka 源码_第2张图片

图2

 Spring Cloud -Eureka 源码_第3张图片

图3

Spring Cloud -Eureka 源码_第4张图片 图4

主类中最重要的是这个注解@SpringBootApplication 

 图5

Spring Cloud -Eureka 源码_第5张图片

正常启动后的页面

图6

Spring Cloud -Eureka 源码_第6张图片

图7

Spring Cloud -Eureka 源码_第7张图片

 这个类的作用就是激活EurekaServerAuoConfiguration 这个类。在spring 启动的时候启动。

图8

Spring Cloud -Eureka 源码_第8张图片

spring 在启动的时候会把这个类加载到容器中。但是并一定启动。 图9 。是否启动要看注解配置 @ConditionalOnBean ,是否在容器中有EurekaServerMarkerConfiguration这个类 ,才会真正的被spring容器中启动。EurekaServerAuoConfiguration,;还有其他的一些配置文件 @EnableConfigurationProperties 图12 ; @Import 的 EurekaServerInitializerConfiguration; 初始化一些东西 图13。

Spring Cloud -Eureka 源码_第9张图片

Spring Cloud -Eureka 源码_第10张图片

eureka的配置图10 ,初始化一个EurekaServer的一些配置。

Spring Cloud -Eureka 源码_第11张图片

Spring Cloud -Eureka 源码_第12张图片

Spring Cloud -Eureka 源码_第13张图片

Spring Cloud -Eureka 源码_第14张图片

Spring Cloud -Eureka 源码_第15张图片

Spring Cloud -Eureka 源码_第16张图片

eurekaServer的启动。图

Spring Cloud -Eureka 源码_第17张图片

Spring Cloud -Eureka 源码_第18张图片

图9

Spring Cloud -Eureka 源码_第19张图片

 

图10

Spring Cloud -Eureka 源码_第20张图片

 Spring Cloud -Eureka 源码_第21张图片

 Spring Cloud -Eureka 源码_第22张图片

Spring Cloud -Eureka 源码_第23张图片

图11

Spring Cloud -Eureka 源码_第24张图片

这个bean里面回放入我们很多的eureka里很多关键性的配置。

图12

Spring Cloud -Eureka 源码_第25张图片

 一些其他的配置文件。

图13

Spring Cloud -Eureka 源码_第26张图片

Spring Cloud -Eureka 源码_第27张图片

Spring Cloud -Eureka 源码_第28张图片

实现start()方法。

Spring Cloud -Eureka 源码_第29张图片

Spring Cloud -Eureka 源码_第30张图片

如果isAutoStartup ()方法返回true 的时候,spring回调上面的start方法。

图14

Spring Cloud -Eureka 源码_第31张图片

Spring Cloud -Eureka 源码_第32张图片

启动初始化。

图15

Spring Cloud -Eureka 源码_第33张图片

生命周期的接口

图16

Spring Cloud -Eureka 源码_第34张图片

初始化运行时环境,初始化eureka 的上下文。

图17

Spring Cloud -Eureka 源码_第35张图片

Spring Cloud -Eureka 源码_第36张图片

图18

Spring Cloud -Eureka 源码_第37张图片

 

Spring Cloud -Eureka 源码_第38张图片

156行当我们要调用 registry. opetForTraffic()  这个方法是发现这个接口有多个实现,到底用那个类实现?看下registry的定义,图20

 

图19

Spring Cloud -Eureka 源码_第39张图片

图20

 Spring Cloud -Eureka 源码_第40张图片

发现他是通过EurekaServerBootstrap方法示例化的,那在什么时候调用的呢,

图21

Spring Cloud -Eureka 源码_第41张图片 通过这个方法我们就能够确定registry是PeerAwareIntanceREgistry,那PeerAwareIntanceRegistry 怎么初始化的的,图22。

图22

Spring Cloud -Eureka 源码_第42张图片

 初始化peerAwareInstanceRegistry.

图23

Spring Cloud -Eureka 源码_第43张图片

图24

Spring Cloud -Eureka 源码_第44张图片

图25

Spring Cloud -Eureka 源码_第45张图片

 

Spring Cloud -Eureka 源码_第46张图片

图26

Spring Cloud -Eureka 源码_第47张图片

图27

Spring Cloud -Eureka 源码_第48张图片

 延迟多久,定时剔除没有心跳反应的机器。图 29

图28

Spring Cloud -Eureka 源码_第49张图片

图29

Spring Cloud -Eureka 源码_第50张图片

图30

Spring Cloud -Eureka 源码_第51张图片

图31

Spring Cloud -Eureka 源码_第52张图片

Spring Cloud -Eureka 源码_第53张图片

图32 

 Spring Cloud -Eureka 源码_第54张图片

 




客户端源码 

图33

Spring Cloud -Eureka 源码_第55张图片

运行客户端程序。

图34

Spring Cloud -Eureka 源码_第56张图片

Spring Cloud -Eureka 源码_第57张图片

图35

 Spring Cloud -Eureka 源码_第58张图片

Spring Cloud -Eureka 源码_第59张图片

图36

Spring Cloud -Eureka 源码_第60张图片

我们的客户端启动,好像没有什么注解标识和服务端的关系,仅仅是因为我们在图35的配置文件配置了吗

图37

Spring Cloud -Eureka 源码_第61张图片

 那我们先从依赖包看起,

图38

Spring Cloud -Eureka 源码_第62张图片

Spring Cloud -Eureka 源码_第63张图片

核心代码应该是28行。

图39

Spring Cloud -Eureka 源码_第64张图片

在这个包里看下,

 图40

Spring Cloud -Eureka 源码_第65张图片

@ConditionalOnBean这个类是不是和服务端的很像啊, @AutoConfigureAfter这个注解的意思是加载 这个注解 之后的类以后,才加载EurekaClientAutoConfiguration这个类。 @AutoConfigureAfter注解中包含三个类,其中EurekaDiscoveryClientConfiguration和我们的client有关系。图42

Spring Cloud -Eureka 源码_第66张图片

 初始化EurekaClientConfigBean   109行,

Spring Cloud -Eureka 源码_第67张图片

Spring Cloud -Eureka 源码_第68张图片

Spring Cloud -Eureka 源码_第69张图片

Spring Cloud -Eureka 源码_第70张图片

206行 DiscoveryClient是 spring 对eureka Clicent类的一种封装。 真正的eureka Client是 EurekaClient类,那么问题来了什么时候初始化的EurekaClient类呢,

Spring Cloud -Eureka 源码_第71张图片

详细代码图46 

图41

Spring Cloud -Eureka 源码_第72张图片

图42

Spring Cloud -Eureka 源码_第73张图片

ConditionalOnProperty 这个注解,默认是true,只有这个注解,EurenkaDisccverClientConfiguration才会启作用。

图 43

Spring Cloud -Eureka 源码_第74张图片

Spring Cloud -Eureka 源码_第75张图片

Spring Cloud -Eureka 源码_第76张图片

Spring Cloud -Eureka 源码_第77张图片

图44

Spring Cloud -Eureka 源码_第78张图片

图45

Spring Cloud -Eureka 源码_第79张图片

图46

Spring Cloud -Eureka 源码_第80张图片

Spring Cloud -Eureka 源码_第81张图片 当调用63行,super时,图48

图47

Spring Cloud -Eureka 源码_第82张图片

父类是DiscoveryClient

图48

Spring Cloud -Eureka 源码_第83张图片

当我们269行,this时图49

图49

Spring Cloud -Eureka 源码_第84张图片

Spring Cloud -Eureka 源码_第85张图片

 Spring Cloud -Eureka 源码_第86张图片

定时任务,心跳, 刷新。 

 Spring Cloud -Eureka 源码_第87张图片

Spring Cloud -Eureka 源码_第88张图片

Spring Cloud -Eureka 源码_第89张图片 435行,我们看到注释 初始化定时任务,其中定时任务有集群解析, 心跳检测,示例的复制,拉取注册表

图50

Spring Cloud -Eureka 源码_第90张图片

 定时拉取注册表的。Spring Cloud -Eureka 源码_第91张图片

服务续约图59-0

Spring Cloud -Eureka 源码_第92张图片

 Spring Cloud -Eureka 源码_第93张图片

初始化注册任务。

 Spring Cloud -Eureka 源码_第94张图片

相当于配置文件的这两个属性,如果不配置默认为true; 如果是服务端单节点的,需要配置两个为false的。对于客户端来说都会执行的,

Spring Cloud -Eureka 源码_第95张图片

 这里写错了,应该是Eureka Server 也会维护一个只读的服务清单缓存。

Spring Cloud -Eureka 源码_第96张图片

Spring Cloud -Eureka 源码_第97张图片

 Spring Cloud -Eureka 源码_第98张图片

 

Spring Cloud -Eureka 源码_第99张图片

1248  行 定时任务,默认每30秒,从服务端获取服务列表。 scheduler.schedule() 这个方法是一次性调用,为什么说每隔30秒获取呢,

 图51

Spring Cloud -Eureka 源码_第100张图片

图52

Spring Cloud -Eureka 源码_第101张图片

 

这里有三个闪光点,第一是并发编程的使用,第二是时间翻倍, future.get() 获取超时抛异常后(说明这个任务30秒不可能完成,所以给他翻倍),会获取他的值 ,把原来的值扩大两倍,然后取扩大后的值和最大值最小的那个值,作为延迟后的时间。 第三个是时间还原;如果是这个任务是偶尔一次性 30秒不能完成在把时间翻倍,就不太合适了。这里的做法是 future.get() 获取超时,如果第三次,第四次获取不超时就会把原来的值设置回去。65行。 如果用TimedSupervisorTask,不能实现这样灵活的时间翻倍。

Spring Cloud -Eureka 源码_第102张图片

 Spring Cloud -Eureka 源码_第103张图片

 当我们看到96行才知道,在schenduler.schedule()的方法里面有重新调用了一次. schenduler.schedule(),所以他有每隔30秒。

图53

分析一下task;

 

Spring Cloud -Eureka 源码_第104张图片

图54

Spring Cloud -Eureka 源码_第105张图片

Spring Cloud -Eureka 源码_第106张图片

 1451行到1470行 是亚马逊的整合部分,不用看,

Spring Cloud -Eureka 源码_第107张图片

1473行拉去注册表。

图55

Spring Cloud -Eureka 源码_第108张图片 947,948行代码注释,如果增量被禁止,或者是第一次的时候拉去全部的注册表。当第一次的时候,applications肯定为空。判断是否增量拉取是否禁止。这个是可以配置。如果为true 就是全量拉取,如果为false就是增量获取 965行获取和存储注册表。图57

图56

Spring Cloud -Eureka 源码_第109张图片

 

 这个是本地缓存

Spring Cloud -Eureka 源码_第110张图片

Spring Cloud -Eureka 源码_第111张图片

图57

 Spring Cloud -Eureka 源码_第112张图片

我们拉取全量的的注册表,并保存本地。1051行,获取全量注册表,利用Eureka client调用Euredka Server 方法返回。

1061行保存到本地缓存中。

图58

图59

Spring Cloud -Eureka 源码_第113张图片

 187行最终拼接的地址。

 

图59-0

Spring Cloud -Eureka 源码_第114张图片

服务续约的任务

 图59-1

Spring Cloud -Eureka 源码_第115张图片

图59-2

Spring Cloud -Eureka 源码_第116张图片

图59-3

Spring Cloud -Eureka 源码_第117张图片

服务注册

图59-4

Spring Cloud -Eureka 源码_第118张图片

 图59-5

Spring Cloud -Eureka 源码_第119张图片

图59-6 

Spring Cloud -Eureka 源码_第120张图片

图59-7

根据这个接口去服务端找对应的接口。

 

图60

Spring Cloud -Eureka 源码_第121张图片

eureka server 对外提供的接口。 

图61

Spring Cloud -Eureka 源码_第122张图片

 但是我们发现一个小问题,即便我们的服务器启动了,也要等一段时间才可以出数据。

 

 

增量的获取

图61-0

Spring Cloud -Eureka 源码_第123张图片

图61-2 

 Spring Cloud -Eureka 源码_第124张图片

 首先也是利用eureka client调用 增量接口。如果增量的数据为空,为了安全起见他有调用了全量获取。如果增量不为null 需要把原来的全量和增量合并所以需要加锁。如果不加锁 其他线程操作,数据就乱套了。现在有一种场景,客户端每30秒钟去服务端拉取 注册表,第一次是全量,第二次拉取的时候网络有问题导致没有拉取到,第三 ,四,五,六,次也没有拉取到,这个时候服务端也有一个缓存这个缓存3分钟会失效,正好3分钟后服务端缓存失效,那么客户端来拉取增量的时候为空,这种情况下 ,客户端的注册表和服务端的注册表是不一致的。1100行这个方法就是解决这个问题的。 图61-4 通过从增量中拉取的hashcode和 本地的hashcode做比较,不一致的话从新拉取全量。

Spring Cloud -Eureka 源码_第125张图片

 不一致的话会全量调用。图61-5

图61-3

Spring Cloud -Eureka 源码_第126张图片

合并:遍历增量  ,通过增量的名字取本地的全量中查找如果没有直接 放入,

 Spring Cloud -Eureka 源码_第127张图片

Spring Cloud -Eureka 源码_第128张图片

 图61-4

Spring Cloud -Eureka 源码_第129张图片

 getReconcileHashCode()  

图61-5

Spring Cloud -Eureka 源码_第130张图片

 Spring Cloud -Eureka 源码_第131张图片Spring Cloud -Eureka 源码_第132张图片

图61-5

Spring Cloud -Eureka 源码_第133张图片

 



以下是服务端的源码

图62

Spring Cloud -Eureka 源码_第134张图片

Spring Cloud -Eureka 源码_第135张图片

  Spring Cloud -Eureka 源码_第136张图片

  156行 关键代码 图64

 图63

Spring Cloud -Eureka 源码_第137张图片

Spring Cloud -Eureka 源码_第138张图片

图64

Spring Cloud -Eureka 源码_第139张图片

 Spring Cloud -Eureka 源码_第140张图片

如果是只读缓存,先从读缓存中获取,如果对缓存 为空再从读写缓存中获取,并返回。 那问题又来了读写缓存也没有呢,图66 

图65

Spring Cloud -Eureka 源码_第141张图片

 图66

Spring Cloud -Eureka 源码_第142张图片

 readWriteCacheMap 初始化, 初始化1000的容器,默认写多长时间实现,后面单位为秒。

Spring Cloud -Eureka 源码_第143张图片

默认从这个里面获取。

Spring Cloud -Eureka 源码_第144张图片

 每30秒回刷新 我们的只读缓存

Spring Cloud -Eureka 源码_第145张图片

 比较只读缓存和读写缓存的是否一致,不一致就更新。

图67 

Spring Cloud -Eureka 源码_第146张图片

我们看All_Apps  411行亚马逊的不用看,416行重点。

图68

Spring Cloud -Eureka 源码_第147张图片

图69

Spring Cloud -Eureka 源码_第148张图片

registry 是一个服务注册的一个注册表。

Spring Cloud -Eureka 源码_第149张图片

 


服务端注册的接口 

图70

Spring Cloud -Eureka 源码_第150张图片 Spring Cloud -Eureka 源码_第151张图片

 

 图71

图72 

Spring Cloud -Eureka 源码_第152张图片

图 73

Spring Cloud -Eureka 源码_第153张图片

Spring Cloud -Eureka 源码_第154张图片

Spring Cloud -Eureka 源码_第155张图片

Spring Cloud -Eureka 源码_第156张图片

Spring Cloud -Eureka 源码_第157张图片

真正注册表的结构是这样

首先获取一个gmap 如果为空直接放一下,

Spring Cloud -Eureka 源码_第158张图片

 Spring Cloud -Eureka 源码_第159张图片

还有上次更新时间,注册时间,启动时间

Spring Cloud -Eureka 源码_第160张图片

 Spring Cloud -Eureka 源码_第161张图片

Spring Cloud -Eureka 源码_第162张图片

Spring Cloud -Eureka 源码_第163张图片

历史信息就是客户端注册过来的信息。

Spring Cloud -Eureka 源码_第164张图片

具体的示例。

 

Spring Cloud -Eureka 源码_第165张图片

注册表的示例

Spring Cloud -Eureka 源码_第166张图片

放完之后的gMap  

Spring Cloud -Eureka 源码_第167张图片

Spring Cloud -Eureka 源码_第168张图片

 注册完之后,缓存失效。

图74

Spring Cloud -Eureka 源码_第169张图片

Spring Cloud -Eureka 源码_第170张图片 为什么要用两级缓存,解决频繁读写,读写分离; 比如想淘宝,这种大型的互联网公司,有几千个客户端,每30秒都要定时执行心跳任务续期,需要更新注册表的最后更新时间,每30分钟需定时拉新最新的注册表,读和写并且是互斥,这样的性能并不是很高。这样读的时候只读我读的map,写的时候只写那个 registy, 两个缓存定时失效。

图75

Spring Cloud -Eureka 源码_第171张图片

 问题来了,如果将新的示例信息注册大数据map中,清理缓存,invalidateCache  readWriteCacheMap 失效了,单是readOnlyCacheMap没有失效。数据不是不一致了吗  ,因为他是满足CAP 中的 AP思想 高可用的最终一致性。

Spring Cloud -Eureka 源码_第172张图片

图76

Spring Cloud -Eureka 源码_第173张图片

 Spring Cloud -Eureka 源码_第174张图片

 evictionTimestamp标识当前的示例已经过期了 默认为0 已经做了标记,但是这个示例还在注册表还没有被移除 。lastUpdateTimesTamp上次续约的时间。

 剔除逻辑的bug,并不是90秒剔除,而是180秒剔除,因为有这个bug,duration默认是90秒。只需要更新当前时间就可以了,不应该加duration了。‘’看方法注释。

 

Spring Cloud -Eureka 源码_第175张图片

 相关文档总结:感谢诸葛老师

Eureka服务端Jersey接口

Spring Cloud -Eureka 源码_第176张图片


Eureka服务端源码分析.png

Spring Cloud -Eureka 源码_第177张图片 

 


Eureka客户端源码分析

Spring Cloud -Eureka 源码_第178张图片

 

 

 

你可能感兴趣的:(spring,cloud)