2、SpringCloud-Eureka服务注册中心
一、服务注册中心
注意:服务注册中心本质上是为了解耦服务提供者和服务消费者。
对于任何一个微服务,原则上都应存在或者支持多个提供者(比如简历微服务部署 多个实例),这是由微服务的分布式属性
决定的。更进一步,为了支持弹性扩缩容特性,一个微服务的提供者的数量和分布往往是动 态变化的,也是无法预先确定的。因此,原本在单体应用阶段常用的静态LB机制就 不再适用了,需要引入额外的组件来管理微服务提供者的注册与发现,而这个组件 就是服务注册中心
二、服务注册中心的一般原理
分布式微服务架构中,服务注册中心用于存储服务提供者地址信息、服务发布相关的属性信息,消费者通过主动查询和被动通知的方式获取服务提供者的地址信息,而不再需要通过硬编码方式得到提供者的地址信息。消费者只需要知道当前系统发布了那些服务,而不需要知道服务具体存在于什么位置,这就是透明化路由
- 1)服务提供者启动
- 2)服务提供者将相关服务信息主动注册到注册中心
- 3)服务消费者获取服务注册信息:
- pull模式:服务消费者可以主动拉取可用的服务提供者清单
- push模式:服务消费者订阅服务(当服务提供者有变化时,注册中心也会主动推送 更新后的服务清单给消费者
- 服务消费者直接调用服务提供者
- 另外,注册中心也需要完成服务提供者的健康监控,当发现服务提供者失效时需要及时剔除;
三、主流服务中心对比 Zookeeper
3.1Zookeeper
它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主 要是用来解决分布式应 用中经常遇到的一些数据管理问题,如:统一命名服 务、状态同步服务、集群管理、分布式应用配置项的管理等。
简单来说zookeeper本质=存储+监听通知。
znode
Zookeeper 用来做服务注册中心,主要是因为它具有节点变更通知功能,只要 客户端监听相关服务节点,服务节点的所有变更,都能及时的通知到监听客户 端,这样作为调用方只要使用 Zookeeper 的客户端就能实现服务节点的订阅和 变更通知功能了,非常方便。另外,Zookeeper 可用性也可以,因为只要半数 以上的选举节点存活,整个集群就是可用的。3
3.2 Eureka
由Netflix开源,并被Pivatal集成到SpringCloud体系中,它是基于 RestfulAPI ⻛格开发的服务注册与发现组件。
3.3 Consul
Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务 发布和注册服务软件, 采用Raft算法保证服务的一致性,且支持健康检查。
3.4 Nacos
Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平 台。简单来说 Nacos 就是 注册中心 + 配置中心的组合,帮助我们解决微服务开 发必会涉及到的服务注册 与发现,服务配置,服务管理等问题。Nacos 是 Spring Cloud Alibaba 核心组件之一,负责服务注册与发现,还有配置。
四、服务注册中心组件 Eureka
4.1 Eureka 交互流程及原理
Eureka 包含两个组件:Eureka Server 和 Eureka Client,Eureka Client是一个 Java客户端,用于简化与Eureka Server的交互;Eureka Server提供服务发现的 能力,各个微服务启动时,会通过Eureka Client向Eureka Server 进行注册自己 的信息(例如网络信息),Eureka Server会存储该服务的信息
-
2)图中每一个Eureka Server都是一个集群。
-
3)图中Application Service作为服务提供者向Eureka Server中注册服务, Eureka Server接受到注册事件会在集群和分区中进行数据同步,Application Client作为消费端(服务消费者)可以从Eureka Server中获取到服务注册信 息,进行服务调用。
-
4)微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒) 以续约自己的信息
-
5)Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒)
-
6)每个Eureka Server同时也是Eureka Client,多个Eureka Server之间通过复 制的方式完成服务注册列表的同步
-
7)Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节 点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者
Eureka通过心跳检测、健康检查和客户端缓存等机制,提高系统的灵活性、可 伸缩性和可用性。
4.2 搭建Eureka Server 服务注册中心
4.2.1 pom工程中加入依赖
<dependencies>
<!--Eureka server依赖--> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
4.2.2 application.yml
#Eureka server服务端口 server:
port: 8761
spring:
application:
name: lagou-cloud-eureka-server # 应用名称,会在Eureka中作为服务的
id标识(serviceId) eureka:
instance:
hostname: localhost
client:
service-url: # 客户端与EurekaServer交互的地址,如果是集群,也需要写其
它Server的地址 defaultZone:
http://${eureka.instance.hostname}:${server.port}/eureka/ register-with-eureka: false # 自己就是服务不需要注册自己 fetch-registry: false #自己就是服务不需要从Eureka Server获取服务信息,默认为true,置为false
4.2.3 SpringBoot启动类,使用@EnableEurekaServer声明当前项目为EurekaServer 服务
@SpringBootApplication
// 声明本项目是一个Eureka服务
@EnableEurekaServer
public class LagouCloudEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(LagouCloudEurekaServerApplication.class,args);
}
}
4.3 微服务提供者—>注册到Eureka Server集群
4.3.1 父工程中引入spring-cloud-commons依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
4.3.2 pom文件引入坐标,添加eureka client的相关坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
4.3.3 配置application.yml文件,在application.yml 中添加Eureka Server高可用集群的地址及相关配置
eureka:
client:
serviceUrl: # eureka server的路径 defaultZone:
http://lagoucloudeurekaservera:8761/eureka/,http://lagoucloudeur ekaserverb:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也 可以只写一台,因为各个 eureka server 可以同步注册表
instance: #使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经
过实验都是ip)
prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早
期版本是ipAddress
instance-id: ${spring.cloud.client.ip-
address}:${spring.application.name}:${server.port}:@project.vers
ion@
4.3.4 启动类添加注解
@SpringBootApplication
@EnableEurekaClient // 开启Eureka client
//@EnableDiscoveryClient // 开启注册中心客户端 (通用性注解,比如注册到Eureka、Nacos)
public class ServiceResumeApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceResumeApplication.class, args);
}
}
-
1)从Spring Cloud Edgware版本开始,@EnableDiscoveryClient 或 @EnableEurekaClient 可省略。只需加 上相关依赖,并进行相应配置,即可将 微服务注册到服务发现组件上。
-
2)@EnableDiscoveryClient和@EnableEurekaClient二者的功能是一样的。但 是如果选用的是eureka服务器,那么就推荐@EnableEurekaClient,如果是其 他的注册中心,那么推荐使用@EnableDiscoveryClient,考虑到通用性,后期 我们可以使用@EnableDiscoveryClient
4.4 微服务消费者—>注册到Eureka Server集群
4.4.1 pom文件引入坐标,添加eureka client的相关坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
4.4.2 配置application.yml文件
server:
port: 8090
eureka:
client:
serviceUrl: # eureka server的路径
defaultZone: http://lagoucloudeurekaservera:8761/eureka/,http://lagoucloudeurekaserverb:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也 可以只写一台,因为各个 eureka server 可以同步注册表
instance: #使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)
prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddress
instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:@project.version@
spring:
application:
name: lagou-service-autodeliver
4.4.3 在启动类添加注解@EnableDiscoveryClient,开启服务发现
@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现
public class AutodeliverApplication {
public static void main(String[] args) {
SpringApplication.run(AutodeliverApplication.class,
args); }
}
5. Eureka细节详解
5.1 Eureka元数据详解
Eureka的元数据有两种:标准元数据和自定义元数据。
标准元数据
:主机名、IP地址、端口号等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。自定义元数据
:可以使用eureka.instance.metadata-map配置,符合KEY/VALUE的 存储格式。这 些元数据可以在远程客户端中访问。
自定义元数据
instance:
prefer-ip-address: true
metadata-map:
# 自定义元数据(kv自定义)
cluster: cl1
region: rn1
5.2 Eureka客户端详解
服务提供者(也是Eureka客户端)要向EurekaServer注册服务,并完成服务续约等工作
5.2.1 服务注册详解(服务提供者)
- 1)当我们导入了eureka-client依赖坐标,配置Eureka服务注册中心地址
- 2)服务在启动时会向注册中心发起注册请求,携带服务元数据信息
- 3)Eureka注册中心会把服务的信息保存在Map中。
5.2.2 服务续约详解(服务提供者)
服务每隔30秒会向注册中心续约(心跳)一次(也称为报活),如果没有续约,租约在 90秒后到期,然后服务会被失效。每隔30秒的续约操作我们称之为心跳检测
5.2.3 调整这两个配置
#向Eureka服务中心集群注册服务
eureka:
instance:
# 租约续约间隔时间,默认30秒
lease-renewal-interval-in-seconds: 30
# 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发生心跳,EurekaServer会将服务从列表移除
lease-expiration-duration-in-seconds: 90
5.2.4 获取服务列表详解(服务消费者)
每隔30秒服务会从注册中心中拉取一份服务列表,这个时间可以通过配置修改。
也可以调整配置
#向Eureka服务中心集群注册服务
eureka:
client:
# 每隔多久拉取一次服务列表
registry-fetch-interval-seconds: 30
- 1)服务消费者启动时,从 EurekaServer服务列表获取只读备份,缓存到本地
- 2)每隔30秒,会重新获取并更新数据
- 3)每隔30秒的时间可以通过配置eureka.client.registry-fetch-interval-seconds修 改
5.3 Eureka服务端详解
5.3.1 服务下线
- 1)当服务正常关闭操作时,会发送服务下线的REST请求给EurekaServer。
- 2)服务中心接受到请求后,将该服务置为下线状态
5.3.2 失效剔除
Eureka Server会定时(间隔值是eureka.server.eviction-interval-timer-in-ms,默 认60s)进行检查,如果发现实例在在一定时间(此值由客户端设置的 eureka.instance.lease-expiration-duration-in-seconds定义,默认值为90s)内没 有收到心跳,则会注销此实例。
5.3.3 自我保护
定期的续约(服务提供者和注册中心通信),假如服务提供者和注册中心之间的网络有点问题,不代表服务提供者不可用,不代表服务消费者无法访问服务提供者 如果在
15分钟内超过85%的客户端节点都没有正常的心跳
,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制
为什么会有自我保护机制?
默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务 实例的心跳,Eureka Server将会移除该实例。但是当网络分区故障发生时,微服务 与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除 这个微服务,所以引入了自我保护机制
当处于自我保护模式时
-
1)不会剔除任何服务实例(可能是服务提供者和EurekaServer之间网络问题),保 证了大多数服务依然可用
-
2)Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它 节点上,保证当前节点依然可用,当网络稳定时,当前Eureka Server新的注册信息 会被同步到其它节点中。
-
3)在Eureka Server工程中通过eureka.server.enable-self-preservation配置可用 关停自我保护,默认值是打开
eureka:
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
6. Eureka核心源码剖析
6.1 Eureka Server启动过程
-
springboot应用启动时会加载EurekaServerAutoConfiguration自动配置类
-
需要有一个marker bean,才能装配Eureka Server,那么这个marker 其实是@EnableEurekaServer注解决定的,也就是说只有添加了@EnableEurekaServer注解,才会有后续的动作,这是成为一 个EurekaServer的前提
- 而在 com.netflix.eureka.cluster.PeerEurekaNodes#start方法中
- EurekaServerInitializerConfiguration,重点关注,进入 EurekaServerBootstrap#contextInitialized
6.2 Eureka Server服务接口暴露策略
在Eureka Server启动过程中主配置类注册了Jersey框架(是一个发布restful⻛格接口的框架,类似于我们的springmvc)
6.3 Eureka Server服务注册接口(接受客户端注册服务)
- ApplicationResource类的addInstance()方法中代码:registry.register(info, "true".equals(isReplication));
- com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#register - 注册服务 信息并同步到其它Eureka节点
- AbstractInstanceRegistry#register():注册,实例信息存储到注册表是一个 ConcurrentHashMap
6.4 Eureka Server服务续约接口(接受客户端续约)
- InstanceResource的renewLease方法中完成客户端的心跳(续约)处理,关键代 码:registry.renew(app.getName(), id, isFromReplicaNode);
6.5 Eureka Client注册服务
启动过程:Eureka客户端在启动时也会装载很多配置类,我们通过spring-cloud- netflix-eureka-client-2.1.0.RELEASE.jar下的spring.factories文件可以看到加载的配 置类
- EurekaClientAutoConfiguration
- 1)读取配置文件
- 2)启动时从EurekaServer获取服务实例信息
- 3)注册自己到EurekaServer(addInstance)
- 4)开启一些定时任务(心跳续约,刷新本地服务缓存列表)
6.6 Eureka Client下架服务
com.netflix.discovery.DiscoveryClient#shutdown
本文作者:志旋
本文链接:https://www.cnblogs.com/wuzhixuan/p/16011234.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步