前言:之所以写这篇文章,第一个原因是刚入职的这家新公司,里边使用到了这个组件,但是却没有真正的推广开,还在摸索探讨阶段,自己之前学习springCloud的时候,有学习过相关内容,但是没有去总结一下,以至于现在你问Eureka是干嘛的,除了知道这个是个注册中心,其他的好像都是空白了,这样的感觉不太好。。。
前言里边提到过Eureka是用于注册中心的,那么注册中心的作用又主要是干什么的?注册中心的本质是为了接耦服务提供者和服务消费者。
分布式微服务架构中,服务注册中⼼⽤于存储服务提供者地址信息、服务发布相关的属性信息,消费者通过主动查询和被动通知的⽅式获取服务提供者的地址信息, ⽽不再需要通过硬编码⽅式得到提供者的地址信息。消费者只需要知道当前系统发布了那些服务,⽽不需要知道服务具体存在于什么位置,这就是透明化路由。
Eureka 包含两个组件:Eureka Server 和 Eureka Client,Eureka Client是⼀个 Java客户端,⽤于简化与Eureka Server的交互;Eureka Server提供服务发现的 能⼒,各个微服务启动时,会通过Eureka Client向Eureka Server 进⾏注册⾃⼰ 的信息(例如⽹络信息),Eureka Server会存储该服务的信息;
流程说明:
Eureka通过⼼跳检测、健康检查和客户端缓存等机制,提⾼系统的灵活性、可伸缩性和可⽤性。
服务端:@EnableEurekaServer // 声明本项⽬是⼀个Eureka服务
客户端:@EnableDiscoveryClient // 开启服务发现
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/check/{userId}")
public Integer findOpenState(@PathVariable Long userId) {
// TODO 从Eureka Server中获取我们关注的那个服务的实例信息以及接口信息
// 1、从 Eureka Server中获取lagou-service-resume服务的实例信息(使用客户端对象做这件事)
List<ServiceInstance> instances = discoveryClient.getInstances("yuan-service-resume");
// 2、如果有多个实例,选择一个使用(负载均衡的过程)
ServiceInstance serviceInstance = instances.get(0);
// 3、从元数据信息获取host port
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();
String url = "http://" + host + ":" + port + "/resume/openstate/" + userId;
System.out.println("===============>>>从EurekaServer集群获取服务实例拼接的url:" + url);
// 调用远程服务—> 微服务接口 RestTemplate -> JdbcTempate
// httpclient封装好多内容进行远程调用
Integer forObject = restTemplate.getForObject(url, Integer.class);
return forObject;
}
标准元数据:主机名、IP地址、端⼝号等信息,这些信息都会被发布在服务注册表 中,⽤于服务之间的调⽤。 ⾃定义元数据:可以使⽤eureka.instance.metadata-map配置,符合KEY/VALUE的 存储格式。这 些元数据可以在远程客户端中访问。debug一下ServiceInstance数据就知道了;
# 自定义Eureka元数据
metadata-map:
cluster: cl1
region: rn1
服务提供者(也是Eureka客户端)要向EurekaServer注册服务,并完成服务续约等⼯作
服务注册详解(服务提供者)
1)当我们导⼊了eureka-client依赖坐标,配置Eureka服务注册中⼼地址
2)服务在启动时会向注册中⼼发起注册请求,携带服务元数据信息
3)Eureka注册中⼼会把服务的信息保存在Map中。
服务续约详解(服务提供者)
服务每隔30秒会向注册中⼼续约(⼼跳)⼀次(也称为报活),如果没有续约,租约在90秒后到期,然后服务会被失效。每隔30秒的续约操作我们称之为⼼跳检测。
往往不需要我们调整这两个配置:
#向Eureka服务中⼼集群注册服务 eureka:
instance:
# 租约续约间隔时间,默认30秒
lease-renewal-interval-in-seconds: 30
# 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发⽣⼼跳, EurekaServer会将服务从列表移除
lease-expiration-duration-in-seconds: 90
获取服务列表详解(服务消费者)
每隔30秒服务会从注册中⼼中拉取⼀份服务列表,这个时间可以通过配置修改。往往不需要我们调整
#向Eureka服务中⼼集群注册服务
eureka:
client:
# 每隔多久拉取⼀次服务列表
registry-fetch-interval-seconds: 30
1)服务消费者启动时,从 EurekaServer服务列表获取只读备份,缓存到本地
2)每隔30秒,会重新获取并更新数据
3)每隔30秒的时间可以通过配置eureka.client.registry-fetch-interval-seconds修改
服务提供者 —> 注册中⼼
定期的续约(服务提供者和注册中⼼通信),假如服务提供者和注册中⼼之间的⽹络有点问题,不代表服务提供者不可⽤,不代表服务消费者⽆法访问服务提供者
如果在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 # 关闭⾃我保护模式(缺省为打开)
Eureka Server启动过程–springboot的拔插式实现方式
观察eureka-server的jar包,发现在META-INF下⾯有配置⽂件spring.factories
springboot应⽤启动时会加载EurekaServerAutoConfiguration⾃动配置类
EurekaServerAutoConfiguration类
⾸先观察类头分析
图中的 1)需要有⼀个marker bean,才能装配Eureka Server,那么这个marker其实是由@EnableEurekaServer注解决定的。
也就是说只有添加了@EnableEurekaServer注解,才会有后续的动作,这是成为⼀个EurekaServer的前提。(springboot的拔插式实现方式)。
EurekaClient注册服务
启动过程:Eureka客户端在启动时也会装载很多配置类,我们通过spring-cloud-
netflix-eureka-client-2.1.0.RELEASE.jar下的spring.factories⽂件可以看到加载的配置类
引⼊jar就会被⾃动装配,分析EurekaClientAutoConfiguration类头
如果不想作为客户端,可以设置eureka.client.enabled=false