Eureka简介
Eureka是Netflix开源的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。Spring Cloud将他集成于Spring Cloud Netflix中,从而实现微服务的注册与发现。就CAP原理而言,同为注册中心的ZooKeeper保证了CP(强一致性、分区容错性),而Eureka保证了AP(可用行和分区容错性),当Eureka注册中心出现某个节点宕机时,注册中心集群仍然工作,但是Eureka Client查询到的注册信息不是最新的,也就是牺牲强一致性,但是保证最终一致性。
Eureka架构
从下面Eureka架构图中我们可以发现,架构中的一些重要元素:
- Eureka Server:扮演服务注册中心的角色,可以是单机,也可以是集群,
- Application Service:服务的提供方,向Eureka Server注册服务,是一个Eureka Client并周期性进行续租(也称作为心跳检测),同时可以从Eureka Server获取服务的注册信息。
- Application Client:服务的消费方,从Eureka Server获取注册到注册中心的服务信息,从而根据需要找到对应的服务发起远程服务调用。
- Eureka Client:Application Service、Application Client和Eureka Server都可以作为Eureka Client注册到注册中心。
源码分析
通常我们使用@EnableEurekaClient(可以使用@EnableDiscoveryClient代替)注解来开启当前服务的Eureka自动发现配置。使用@EnableEurekaServer来标Eureka Server服务来激活Eureka的相关配置。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class) // @import注解引入配置类Bean到容器
public @interface EnableEurekaServer {
}
进入到@EnableEurekaServer注解的源码,发现没有其他参数,比较显眼的是
@Import(EurekaServerMarkerConfiguration.class)
引入了EurekaServerMarkerConfiguration这个配置类的Bean到容器中,查看这个类的内容如下,核心内容是生成了一个Marker的Bean到容器。到这步依然没有实质性的东西。
@Configuration
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() {
// 生成一个Marker Bean到容器
return new Marker();
}
class Marker {
}
}
来到注解所在的包,在META-INF路径下找到了spring.factories配置文件,该配置类为Spring Boot约定的第三方包Bean配置文件,在Spring启动时会去加载第三方包中META-INF下spring.factories配置文件中的Bean到容器中。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
查看EurekaServerAutoConfiguration源码,可以发现@ConditionalOnBean注解要求在当前Bean初始化之前,在容器中必须先要有Marker的Bean。联系上文,@EnableEurekaServer的所做的就是把Marker的Bean放到容器中。因此,实现了Eureka Server开关的作用。
@Configuration
@Import(EurekaServerInitializerConfiguration.class)
// 表示该Bean只有当容器中存在Marker的Bean的时候才能初始化。
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
// 此处先省略具体内容
...
}
自保护模式
架构哲学:宁可同时保留所有的微服务,也不盲目注销任何健康的微服务。
默认情况下,如果Eureka Server在一定时间内没有接收到某个Eureka Client的心跳,Eureka Server将会注销该实例(默认90s)。
但是当网络分区故障发生时,微服务和Eureka Server之间无法正常通信,Eureka Server会注销这个微服务,但是这个微服务本身是健康的,不应该被注销。
为了解决上述的问题,Eureka Server引入了自我保护机制,当Eureka Server节点进入自动保护模式以后,就会保护服务注册表中的信息。当Eureka Server中续租率低于配置值时(默认为85%,15min,也就是15min内续租失败的比例大于15%),Eureka Server进入自保护模式,不会注销任何服务。当网络故障恢复后,该Eureka Server节点会自动退出保护模式。
可以通过eureka.server.enable-self-preservation = false禁用自我保护模式。
当两个Eureka Server通信中断时会发生什么
- peers之间的同步操作将会失败,server会进入自保护模式来保护当前的状态。
- 部分Eureka Client可能会在出现问题的Eureka Server上进行注册表信息获取,会出现部分服务其上获取到实时准确的信息,而部分获取到的是过时的注册表信息,这里牺牲了强一致性。
- 当网络稳定后,这种情况会自动恢复,一旦peers之间能够恢复通讯,注册表信息会即使更新同步。