1.什么是Eureka?
●Netflix 在设计Eureka时,遵循的就是AP原则
●Eureka是Netflix的一 个子模块,也是核心模块之一。Eureka是一个基于REST的服务, 用于定位服务,以实现云端中间层服务发现和故障转移,服务注册与发现对于微服务来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类似于Dubbo的注册中心,比如Zookeeper;
2.实现原理
●Eureka的基本架构
- SpringCloud封装了NetFlix公司开发的Eureka模块来实现服务注册和发现(对比Zookeeper)
- Eureka采用了C-S的架构设计,EurekaServer 作为服务注册功能的服务器,他是服务注册中心
- 而系统中的其他微服务。使用Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行,SpringCloud的一 些其他模块(比如Zuul)就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑;
- 和Dubbo架构对比:
这是Eureka架构图
这是Dubbo架构图: - Eureka 包含两个组件: Eureka Server和Eureka Client。
- Eureka Server提供服务注册服务,各个节点启动后,会在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会村粗所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
- Eureka Client是一个java客户端,用于简化EurekaServer的交互, 客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将 会从服务注册表中把这个服务节点移除掉(默认周期为90秒)。
●三大角色
- Eureka Server:提供服务的注册于发现。zookeeper是下载一个压缩包,然后启动程序就可以了,但是eureka需要自己写一个程序
- Service Provider:将自身服务注册到Eureka中,从而使消费方能够找到。
- Service Consumer:服务消费方从Eureka中获取注册服务列表,从而找到消费服务。
3.编写Eureka模块
- 下面我们就自己写一个模块:spring-cloud-eureka,这个模块是作为spring-cloud-demo这个父级工程的子模块的,详见上一篇博客。
(1)新建模块
(2)导入pom依赖
<parent>
<artifactId>springcloud-demo</artifactId>
<groupId>edu.ncu.dong</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-eureka</artifactId>
<dependencies>
<!--eureka-server包,不写版本,让他使用父工程的版本,这样可以避免版本冲突报错-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
(3)编写yml配置信息
(4)编写启动类,其实如果新建的是springboot项目,就不用自己写,会自带的有,这只是为了熟悉流程
(5)启动这个服务,发现报错了:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configurationPropertiesBeans' defined in class path resource [org/springframework/cloud/autoconfigure/ConfigurationPropertiesRebinderAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.context.properties.ConfigurationPropertiesBeans]: Factory method 'configurationPropertiesBeans' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
这其实是由于版本不一致导致的,我们回头看版本信息,发现springcloud的版本是“Greenwich.SR1”,这个版本是2019年3月份发布的,但是我们的springboot版本“2.4.5”是2021年4月份发布的,版本不一致,所以选择版本相近的,我们将springboot降版本“2.1.3.RELEASE”,重新启动发现成功了。
(6)访问监控页面:localhost:7001,但是现在是没有可用的服务的
(7)下面我们将之前写好的spring-cloud-provider-dept放入eureka中
1)先在provider中新增eureka的依赖:注意版本
<!--eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
2)在yml配置文件中增加eureka的配置信息:
#erueka
eureka:
client: #服务注册到哪里
service-url:
defaultZone: http://localhost:7001/eureka/
3)在provider启动类上添加注解@EnableEurekaClient
4)先启动eureka,在启动provider,访问localhost:7001,发现注册进了新的服务
5)这个描述信息可以更改的,就在provider的eureka相关配置加上
重新启动8001的服务,发现出现下方这行话,这是eureka的自我保护机制
一句话总结:某时刻某一个微服务不可以用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存!
●默认情况下,如果EurekaServer在一 定时间内没有接收到某个微服务实例的心跳,EurekaServer将 会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka之间无法正常通行,以上行为可能变得非常危险了-因为微服务本身其实是健康的,此时本不应该注销这个服务。Eureka通过 自我保护机制来解决这个问题–当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,EurekaServer就会保护服务注册表中的信息 ,不再删除服务注册表中的数据(也就是不会注销任何微服务) J当网络故障恢复后,该EurekaServer节 点会自动退出自我保护模式。
●在自我保护模式中,EurekaServer会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该EurekaServer节 点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话:好死不如赖活着
●综上,自我保护模式是一 种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮和稳定
●在SpringCloud中, 可以使用eureka. server . enable-self-preservation = false 禁用自我保护模式[不推荐关闭自我保护机制]
回到描述信息:重启eureka服务,发现更改成功了
那个描述信息指向一个请求,可以返回一个json字符串,这个请求也是需要在配置才能访问,需要先导入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后添加配置信息:
点击描述信息:返回了一个配置好的信息
这里补充一个东西,怎样知道eureka注册中心的所有服务以及他们的信息呢,或者说如何让别的服务知道我这个服务的信息呢?
可以使用Discovery类:
1)在ProviderDept_8001启动类添加@EnableDiscoveryClient注解
2)编写暴露的接口:
3)重启,浏览器访问接口,打印了这些信息
4.搭建Eureka集群
因为只有一个注册中心的情况下是不安全全的,万一这个eureka服务崩了,注册中心就没了,所以我们试着搭建一下集群:如图
1.再创建两个模块,用于搭建集群:
2.把前面搭建好的yml和pom和启动类复制到新创建的两个模块下,免得重新写并更改端口号为7002和7003
3.更改eureka.instance.hostname: localhost #服务端主机的名字,可以为主机的ip,由于只有一台机器,是伪集群,所以没办法,只能个更改电脑设置:Windows/System32/drivers/etc/hosts,增加几个映射,但是这样对电脑来说很危险,做完后记得改回来
然后一次更改三个的hostname,因为要唯一,但是只有一台机器,所以才做上面的操作
4.集群间的关联,以7003的为例,就是与7001和7002关联
eureka:
instance:
hostname: eureka7003.com #服务端主机的名字,可以为主机的ip
client:
register-with-eureka: false #是否向注册中心注册自己,由于是服务端,所以不需要注册自己
fetch-registry: false #false表示自己是注册中心
service-url: #监控的页面,url是注册服务的地址,访问就是localhost:7001,不需要其他的后缀
defaultZone: http://eureka7001.com/eureka/, http://eureka7002.com:7002/eureka/ # 默认的是:http://localhost:8761/eureka/
5.将provider-dept发布到集群里
eureka:
client: #服务注册到哪里,这里就是3个都注册
service-url:
defaultZone: http://eureka7001.com/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
6.启动三个eureka服务,然后启动provider服务,访问页面
这样就搭建好了
5.CAP原则是什么?
CAP是什么?
●C (Consistency) 强一致性
●A (Availability) 可用性
●P (Partition tolerance) 分区容错性
CAP的三进二: CA、AP、CP
CAP理论的核心
●一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求
●根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:
- CA:单点集群,满足一致性,可用性的系统,通常可扩展性较差
- CP:满足一致性,分区容错性的系统,通常性能不是特别高
- AP:满足可用性,分区容错性的系统,通常可能对一致性要求低一些
6.同为服务注册中心,Zookeeper和Eureka的区别是什么?
著名的CAP理论指出,-个分布式系统不可能同时满足C (一致性)、A (可用性)、P (容错性)。由于分区容错性P在分布式系统中是必须要保证的,因此我们只能在A和C之间进行权衡。
●Zookeeper保证的是CP:
任何时候对 Zookeeper 的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是 Zookeeper 不能保证每次服务请求都是可达的。从 Zookeeper 的实际应用情况来看,在使用 Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用(例如有三个节点,如果节点一检测到节点三挂了 ,节点二也检测到节点三挂了,那这个节点才算是真的挂了),那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性。
当然,在大多数分布式环境中,尤其是涉及到数据存储的场景,数据一致性应该是首先被保证的,这也是 Zookeeper 设计紧遵CP原则的另一个原因。但是对于服务发现来说,情况就不太一样了,针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。因为对于服务消费者来说,能消费才是最重要的,消费者虽然拿到可能不正确的服务实例信息后尝试消费一下,也要胜过因为无法获取实例信息而不去消费,导致系统异常要好。
●Eureka保证的是AP:
Eureka设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有一 种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其他节点中
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。