Eureka
- 1.Spring Cloud Eureka 简介
- 2.Spring Cloud Eureka 和 Zookeeper 的区别
- 3.Spring Cloud 其他注册中心
- 4.Spring Cloud Eureka 快速入门
- 5.构建高可用的 Eureka-Server 集群
- 6.Eureka 概念的理解
- 7.Eureka 源码分析
1.Spring Cloud Eureka 简介
注册发现中心
Eureka 来源于古希腊词汇,意为“发现了”。在软件领域, Eureka 是 Netflix 在线影片公司开源的一个服务注册与发现的组件,和其他 Netflix 公司的服务组件(例如负载均衡、熔断器、网关等) 一起,被 Spring Cloud 社区整合为 Spring Cloud Netflix 模块。Eureka 是 Netflix 贡献给 Spring Cloud 的一个框架!
2.Spring Cloud Eureka 和 Zookeeper 的区别
2.1 什么是 CAP 原则
在分布式 微服务里面 CAP 定理,问:为什么 zookeeper 不适合做注册中心?
CAP 原则又称 CAP 定理,指的是在一个分布式系统中
一致性(Consistency)
可用性(Availability)
分区容错性(Partition tolerance)(这个特性是不可避免的)
CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
2.2 分布式特征
C : 数据的一致性 (A,B,C 里面的数据是一致的)
ZK 注重数据的一致性。
Eureka 不是很注重数据的一致性!
A: 服务的可用性(若 zk 集群里面的 master 挂了怎么办)Paxos(多数派)
在 zk 里面,若主机挂了,则 zk 集群整体不对外提供服务了,需要选一个新的出来(120s左右)才能继续对外提供服务!
Eureka 注重服务的可用性,当 Eureka 集群只要有一台活着,它就能对外提供服务。
P:分区的容错性(在集群里面的机器,因为网络原因,机房的原因,可能导致数据不会及时同步),它在分布式必须需要实现的特性!
Zookeeper 注重数据的一致性CP,zk(注册中心,配置文件中心,协调中心)
Eureka 注重服务的可用性AP,eureka (注册中心)
3.Spring Cloud 其他注册中心
Spring Cloud 还有别的注册中心 Consul ,阿里巴巴提供 Nacos 都能作为注册中心,我们
的选择还是很多。
3.1 Consul
官网:https://spring.io/projects/spring-cloud-consul
3.2 Nacos
4.Spring Cloud Eureka 快速入门
4.1 搭建 Eureka-server
4.1.1 分析 pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.hguo</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR12</spring-cloud.version> </properties> <dependencies> <!-- eureka 注册中心的服务端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <!-- 依赖管理,cloud 的依赖--> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
4.1.2 修改启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * @author leizi */ // 开启Eureka注册中心服务端 @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
4.1.3 修改配置文件
server: port: 8761 #为什么是 8761,其他端口就报错 spring: application: name: eureka-server #服务名称
4.1.4 访问测试
4.1.5 分析端口 8761
Eureka-Server 不仅提供让别人注册的功能,它也能注册到别人里面,自己注册自己。所以,在启动项目时,默认会注册自己,我们也可以关掉这个功能。
那么往哪个地址注册自己呢?我们看一下源码:
4.2 搭建 Eureka-client
4.2.1 分析 pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.hguo</groupId> <artifactId>eureka-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-client</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR12</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--eureka-client eureka客户端依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
4.2.2 修改启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * @author leizi */ @SpringBootApplication @EnableEurekaClient // 开启Eureka注册中心客户端 public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } }
4.2.3 修改配置文件
server: port: 8001 spring: application: name: eureka-client-a eureka: client: service-url: #eureka 服务端和客户端的交互地址 defaultZone: http://localhost:8761/eureka/
4.2.4 访问测试
4.2.5 再创建项目 client-b
如 client 一样,注意端口和服务名以及启动类上的注解,在测试查看是否注册上去,在 eureka 里面是通过 spring.application.name
来区分服务的。
4.3 同一个服务(客户端)启动多台
4.3.1 IDEA 启动多台服务操作
4.3.2 访问查看
4.4 注册中心的状态认识
- UP:服务是上线的,括号里面是具体服务实例的个数,提供服务的最小单元
- DOWN:服务是下线的
- UN_KONW:服务的状态未知
4.4.1 服务的实例名称
4.4.2 actuator完善监控信息
服务提供者导入依赖:
<!--actuator完善监控信息--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
application.yml配置信息:
#info配置 info: app.name: stt-springcloud # 应用名 company.name: mazha.stt.com # 公司域名
主要作用:可以看到服务是做什么的,用来提示服务信息。不强制使用
4.5 常用配置文件设置
4.5.1 server 中常用的配置
server: port: 8761 spring: application: name: eureka-server eureka: client: service-url: #eureka 服务端和客户端的交互地址,集群用,隔开 defaultZone: http://localhost:8761/eureka fetch-registry: true #是否拉取服务列表 register-with-eureka: true #是否注册自己(单机 eureka 一般关闭注册自己,集群注意打开) server: eviction-interval-timer-in-ms: 30000 #清除无效节点的频率(毫秒)--定期删除 enable-self-preservation: true #server 的自我保护机制,避免因为网络原因造成误剔除,生产环境建议打开 renewal-percent-threshold: 0.85 #85%,如果在一个机房的 client 端,15 分钟内有 85%的 client 没有续约,那么则可能是网络原因,认为服务实例没有问题,不会剔除他们,宁可放过一万,不可错杀一个,确保高可用 instance: hostname: localhost # 服务主机名称 instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 实例 id prefer-ip-address: true # 服务列表以 ip 的形式展示 lease-renewal-interval-in-seconds: 10 # 表示 eureka client 发送心跳给 server 端的频率 lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该实例
4.5.2 client 中常用的配置
server: port: 8080 spring: application: name: eureka-client eureka: client: service-url: #eureka 服务端和客户端的交互地址,集群用,隔开 defaultZone: http://localhost:8761/eureka register-with-eureka: true #注册自己 fetch-registry: true #拉取服务列表 registry-fetch-interval-seconds: 5 # 表示 eureka-client 间隔多久去拉取服务注册信息 instance: hostname: localhost # 服务主机名称 instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 实例id prefer-ip-address: true # 服务列表以 ip 的形式展示 lease-renewal-interval-in-seconds: 10 # 表示 eureka client 发送心跳给 server 端的频率 lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该实例
5.构建高可用的 Eureka-Server 集群
5.1 eureka-server 修改配置文件
5.1.1 server-1
server: port: 8761 spring: application: name: eureka-server #服务名称 eureka: client: fetch-registry: true #是否拉取服务列表 register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务) service-url: defaultZone: http://localhost:8762/eureka/,http://localhost:8763/eureka/ server: eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒) instance: lease-expiration-duration-in-seconds: 90 #server 在等待下一个客户端发送的心跳时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量
5.1.2 server-2
server: port: 8762 spring: application: name: eureka-server #服务名称 eureka: client: fetch-registry: true #是否拉取服务列表 register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务) service-url: defaultZone: http://localhost:8761/eureka/,http://localhost:8763/eureka/ server: eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒) instance: lease-expiration-duration-in-seconds: 90 #server 在等待下一个客户端发送的心跳时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量
5.1.3 server-3
server: port: 8763 spring: application: name: eureka-server #服务名称 eureka: client: fetch-registry: true #是否拉取服务列表 register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务) service-url: defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ server: eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒) instance: lease-expiration-duration-in-seconds: 90 #server 在等待下一个客户端发送的心跳时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量
5.1.4 测试访问查看
发现并没有出现集群信息,只是同一个服务 server 启动了多台 没有数据交互 不是真正意义上的集群。
原因是因为:
http://localhost:8761/eureka/,http://localhost:8762/eureka/
这样写,eureka 认为只有一个机器,就是 localhost所以这里面不能写成一样。
修改主机 hosts 文件,如果你修改了 hosts 文件 发现没有生效 记得在 cmd 里面刷新一下。
5.1.5 重新修改配置文件
5.1.6 测试查看集群信息
5.1.7 最终优化配置文件
server: port: 8761 spring: application: name: eureka-server #服务名称 eureka: client: fetch-registry: true #是否拉取服务列表 register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务) service-url: defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8762/eureka/ server: eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒) instance: lease-expiration-duration-in-seconds: 90 #server 在等待下一个客户端发送的心跳时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量
5.1.8 最终的集群信息
5.2 集群的使用
5.2.1 改造 eureka-client-a 的配置文件
5.2.2 测试
不管哪一台 server 都注册成功了
5.2.3 宕机一台 server
Eureka server 的集群里面,没有主机和从机的概念,节点都是对等的,只要集群里面有一个节点存活,就能保证服务的可用性。只要有一台存活,服务就能注册和调用。
了解一下一个分布式数据一致性协议 Paxos、raft
http://thesecretlivesofdata.com/raft/
zk 是 Paxos
eureka 没有分布式数据一致性的机制 节点都是相同的
nacos是raft
在有主从模式的集群中 一般都要遵循这样的协议 才可以稳定对外提供服务
Zookeeper--Paxos Nacos--raft
6.Eureka 概念的理解
6.1 服务的注册
当项目启动时(eureka 的客户端),就会向 eureka-server 发送自己的元数据(原始数据)
(运行的 ip,端口 port,健康的状态监控等,因为使用的是 http/ResuFul 请求风格),
eureka-server 会在自己内部保留这些元数据(内存中)。(有一个服务列表)(restful 风格,以 http 动词的请求方式,完成对 url 资源的操作)
6.2 服务的续约
项目启动成功了,除了向 eureka-server 注册自己成功,还会定时的向 eureka-server 汇报自己,心跳,表示自己还活着。(修改一个时间)
6.3 服务的下线(主动下线)
当项目关闭时,会给 eureka-server 报告,说明自己要下机了
6.4 服务的剔除(被动下线,主动剔除)
当项目超过了指定时间没有向 eureka-server 汇报自己,那么 eureka-server 就会认为此节点死掉了,会把它剔除掉,也不会放流量和请求到此节点了。
6.5 Eureka保护机制
6.5.1 什么是Eureka保护机制
官方解释: 自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。
默认情况下,Eureka Client
会定时的向 Eureka Server
端发送心跳包,默认是30s
发送一次,目的是告诉 Eureka Server
当前客户端实例还处于存活状态,如果Eureka server
在一定时间内没有收到实例的心跳,便会把该实例从注册表中删除(默认是90
秒),但是,如果短时间内丢失大量的实例心跳,便会触发Eureka server
的自我保护机制的 ,默认自我保护机制处于开启状态,比如在开发测试时,需要频繁地重启微服务实例客户端,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold
和Renews(last min)
,当Renews(last min)
(最后一分钟收到的心跳数)小于Renews threshold
(心跳阈值)的时候,如果某个服务实例宕机掉,触发保护机制,会出现红色的警告:
6.5.2 为什么要自我保护
因为同时保留”好数据”与”坏数据”总比丢掉任何数据要更好,当网络故障恢复后,这个 Eureka 节点会退出”自我保护模式”。
当一个服务未按时进行心跳续约时,在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多数服务依然可用。
为了防止在一定时间内,Eureka Client
与Eureka Server
在网络不同的情况下,Eureka Server误将Eureka Client服务剔除,这个机制是为了对服务进行保护;
6.5.3 如何关闭Eureka自我保护机制
Eureka自我保护机制默认是开启的,如果如果需要关闭自我保护机制,按照下述方式: enable-self-preservation: false
开关关闭掉,然后修改客户端和服务端相关参数,保证异常服务能及时剔除;
6.5.3.1 Eureka Server配置
#Eureka自我保护机制 server: #关闭eureka自我保护机制false(默认为true) enable-self-preservation: false # 配置Eureka Server清理无效节点的时间间隔(单位毫秒,默认60*1000毫秒,即60秒) eviction-interval-timer-in-ms: 2000
6.5.3.2 Eureka Client配置
减短客户端服务发送服务心跳给服务端的时间, 在开发测试时,将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
eureka: instance: #eureka服务端在接受到实例的最后一次发出的心跳后,需要等待多久才可以将此删除,单位为秒(默认为90s),超过时间则剔除(客户端会按照此规则向Eureka服务端发送心跳检测包) lease-expiration-duration-in-seconds: 90 #eureka客户端需要多长时间发送心跳给eureka服务端,单位为秒(默认为30s),(客户端会按照此规则向Eureka服务端发送心跳检测包) lease-renewal-interval-in-seconds: 2
lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒
lease-expiration-duration-in-seconds:服务失效时间,默认值90秒
6.5.4 获取服务列表
当服务消费者启动时,会检测eureka.client.fetch-registry=true
参数的值,如果为true,则会从Eureka Server服务的列表只读备份,然后缓存在本地。并且每隔30秒
会重新获取并更新数据。我们可以通过下面的参数来修改:
eureka: client: #表示eureka client间隔多久去拉取服务器注册信息,默认为30秒 registry-fetch-interval-seconds: 5
生产环境中,我们不需要修改这个值。但是为了开发环境下,能够快速得到服务的最新状态,我们可以将其设置小一点。
7.Eureka 源码分析
了解他的原理 出了问题排查 bug,优化你的代码
7.1 Eureka 运作原理的特点
Eureka-server 对外提供的是 restful 风格的服务,以 http 动词的形式对 url 资源进行操作get、post、put、delete
。
http 服务 + 特定的请求方式 + 特定的 url 地址
只要利用这些 restful 我们就能对项目实现注册和发现,只不过 eureka 已经帮我们使用 java 语言写了 client,让我们的项目只要依赖 client 就能实现注册和发现!只要你会发起 Http 请求,那你就有可能自己实现服务的注册和发现。不管你是什么语言!
7.2 服务注册的源码分析【重点】
7.2.1 Eureka-client 发起注册请求
7.2.1.1 源码位置
7.2.1.2 如何发送信息注册自己
7.2.1.3 真正的注册 AbstractJerseyEurekaHttpClient
总结
当 eureka 启动的时候,会向我们指定的 serviceUrl 发送请求,把自己节点的数据以 post请求的方式,数据以 json 形式发送过去。当返回的状态码为 204 的时候,表示注册成功。
7.2.2 Eureka-server 实现注册+保存
7.2.2.1 接受客户端的请求
com.netflix.eureka.resources.ApplicationResource
7.2.2.2 源码位置
7.2.2.3 接受 client 的注册请求
7.2.2.4 处理请求(注册自己,向其他节点注册)
7.2.2.5 真正的注册自己
7.2.2.6 具体源码分析
7.2.3 服务注册总结
重要的类:
DiscoveryClient 里面的 register()方法完后注册的总体构造
AbstractJerseyEurekaHttpClient 里面的 register()方法具体发送注册请求(post)
InstanceRegistry 里面 register()方法接受客户端的注册请求
PeerAwareInstanceRegistryImpl 里面调用父类的 register()方法实现注册
AbstractInstanceRegistry 里面的 register()方法完成具体的注册保留数据到 map 集合
保存服务实例数据的集合:
第一个 key 是应用名称(全大写) spring.application.name
Value 中的 key 是应用的实例 id eureka.instance.instance-id
Value 中的 value 是 具体的服务节点信息
private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();
7.3 服务续约的源码分析
7.3.1 Eureka-client 发起续约请求
7.3.1.1 如何发请求续约自己
DiscoveryClient 的 renew()方法
7.3.1.2 真正的请求续约自己(AbstractJerseyEurekaHttpClient)
7.3.2 Eureka-server 实现续约操作
7.3.2.1 接受续约的请求
7.3.2.2 真正的续约
7.3.2.3 续约的本质
续约的本质就是修改了服务节点的最后更新时间
duration:代表注册中心最长的忍耐时间,并不是 30s 没有续约就里面剔除,而是 30 +duration(默认是 90s) 期间内没有续约,才剔除服务。
Volatile 标识的变量是具有可见性的,当一条线程修改了我的剔除时间,其他线程就可以立马看到(应用场景:一写多读),后面在剔除里面有一个定时任务,去检查超时从而判断某一个服务是否应该被剔除。
7.4 服务剔除的源码分析(被动下线)
7.4.1 Eureka-server 实现服务剔除
7.4.1.1 在 AbstractInstanceRegistry 的 evict()方法中筛选剔除的节点
7.4.1.2 在 internalCancel 方法里面真正实现剔除
7.4.1.3 什么时候执行服务剔除操作呢?
查看 evict()方法在哪里调用的
具体查看多久执行一次呢?
发现默认是 60s 执行一次
当然我们也可以自定义检测定时器的执行时间
7.5 服务下线的源码分析
7.5.1 Eureka-client 发起下线请求
7.5.1.1 如何发起下线请求
7.5.1.2 真正的发请求下线 AbstractJerseyEurekaHttpClient
7.5.2 Eureka-server 处理下线请求
7.5.2.1 接受下线请求
7.5.2.2 真正的下线服务
7.6 服务发现(源头)
7.6.1 什么是服务发现
7.6.2 测试服务发现
启动 eureka-server 一台
启动服务 a
启动服务 b
确保服务都上线了
7.6.2.1 在 a 服务里面做服务发现
访问 http://localhost:8001/find?serviceId=eureka-client-b
7.6.3 服务发现的源码分析
从 discoveryClient.getInstances(serviceId);方法进去,找到 eureka 的实现。
从 getInstancesByVipAddress 方法进去看到真正的服务发现
在 getInstancesByVirtualHostName 方法里面做真正的服务发现
7.6.3.1 在 eureka-client 客户端也有 map 集合存放服务列表?
我们发现,当我们还没有做服务发现之前,集合里面已经有值了,说明项目启动的时候就去 server 端拉取服务列表并且缓存了起来。
7.6.3.2 到底何时从 server 拉取服务放进去的呢?
在 eureka 的 DiscoverClient 类的一个构造方法里面,有一个任务调度线程池。
查看 initScheduledTasks()这个方法
在 CacheRefreshThread()中
fetchRegistry()方法中判断决定是全量拉取还是增量拉取
getAndStoreFullRegistry()全量拉取
getAndUpdateDelta()增量拉取
7.6.3.3 服务发现总结
重要的类:
DiscoveryClient 类里面的构造方法执行线程初始化调用
CacheRefreshThread 类里面的 run 方法执行服务列表的拉取(方便后期做服务发现)
fetchRegistry()方法去判断全量拉取还是增量拉取
全量拉取发生在:当服务列表为 null 的情况 当项目刚启动就全量拉取
增量拉取发生:当列表不为 null ,只拉取 eureka-server 的修改的数据(注册新的服务,上线服务)
eureka 客户端会把服务列表缓存到本地 为了提高性能
但是有脏读问题,当你启动一个新的应用的时候 不会被老的应用快速发现
本文来自博客园,作者:Lz_蚂蚱,转载请注明原文链接:https://www.cnblogs.com/leizia/p/17324192.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步