SpringCloud核心组件之---Eureka
Posted bodhixhwang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud核心组件之---Eureka相关的知识,希望对你有一定的参考价值。
这篇文章我们来聊一下什么是Eureka,它的具体作用是什么
我之前的文章已经讲过如果搭建一个Eureka服务,如果有兴趣可以看看https://www.cnblogs.com/bodhixhwang/p/13815294.html
1.什么是eureka
Eureka是netflix的一个子核心模块,是一个基于rest的服务,SpringCloud封装了Netflix公司开发的Eureka模块来实现服务注册时和发现。Eureka采用了C-S的设计架构。Eureka Server作为服务注册功能的服务器,它是服务注册时中心。而系统中的其他微服务,使用eureka的客户端连接到eureka server并维持心跳连接。这样系统的维护人员就可以通过eureka server来监控系统中各个微服务是否正常运行。SpringCloud的一些其他模块就可以通过eureka server来发现系统中的其他微服务,并执行相关的逻辑
2.eureka的作用
在微服务系统中,有很多模块服务,这些模块服务的实例就由eureka进行了统一管理,调用时服务ID/名称是唯一标识,根据唯一标识在注册中心找到实例信息,再调用服务。eureka服务端也提供了ui界面,显示每个系统的运行情况,这样系统的维护人员可以通过eurekaserver来监控系统各个服务的运行情况。
3.服务的注册于发现
1)、Eureka服务端:也称服务注册中心,同其他服务注册中心一样,支持高可用配置。如果Eureka以集群模式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中其他分片会把它们的状态再次同步回来
2)、Eureka客户端:主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中,在应用程序运行时,Eureka客户端想注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态
4.我们通过代码演示来了解一下eureka
首先我们创建一个springboot项目,编写启动类,特别注意@EnableEurekaServer注解,这个是声明当前工程是注册中心服务端
1 import org.springframework.boot.SpringApplication; 2 import org.springframework.boot.autoconfigure.SpringBootApplication; 3 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 4 import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; 5 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; 6 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 7 8 @EnableEurekaServer 9 @SpringBootApplication10 public class EurekaStart { 11 public static void main(String[] args) { 12 SpringApplication.run(EurekaStart.class, args); 13 } 14 }
比较简单,这个eureka工程里面只写一个启动类就行,然后我们看看配置文件application.yml
1 eureka: 2 instance: 3 hostname: eureka-service 4 lease-renewal-interval-in-seconds: 60 #定义心跳检测间隔时间 ,默认30秒 5 lease-expiration-duration-in-seconds: 60 #定义服务时效时间,心跳检测后6秒钟服务时效,默认90秒 6 preferIpAddress: true 7 instance-id: ${spring.cloud.client.ipAddress}:${server.port} 8 server: 9 enable-self-preservation: false #关闭自我保护模式 10 eviction-interval-timer-in-ms: 5000 # 驱逐下线服务,间隔5秒,默认60秒 11 client: 12 register-with-eureka: false #关闭自己服务注册 13 service-url: 14 defaultZone: http://localhost:8761/eureka/ 15 fetch-registry: false #关闭检索服务 16 17 server: 18 port: 8761
pom.xml配置文件如下,加入server依赖包,com.parent工程前面的文章介绍过,这是一个公共父类,统一管理组件包,文章的开头也贴上了地址
1 <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 2 <modelVersion>4.0.0</modelVersion> 3 <parent> 4 <groupId>com.cn.bodhi</groupId> 5 <artifactId>com.parent</artifactId> 6 <version>0.0.1-SNAPSHOT</version> 7 </parent> 8 <artifactId>com.eureka</artifactId> 9 <dependencies> 10 <dependency> 11 <groupId>org.springframework.cloud</groupId> 12 <artifactId>spring-cloud-starter-eureka-server</artifactId> 13 <version>1.4.4.RELEASE</version> 14 </dependency> 15 </dependencies> 16 </project>
以上就是eureka-server的全部,然后启动测试,出现如下界面,说明我们eureka服务端已经启动成功,红色的字体是因为我们关闭了自我保护模式,可以在配置文件中修改,ui风格是自定义的,如果自己想修改,同样,参照文章开头的链接修改即可
服务端我们创建好了,接下来我们创建客户端,看看服务注册到界面上是怎么显示的,这儿我们先引入一个新的概念,配置中心config-server,配置中心就是把所有的配置文件进行统一管理,文件之间可以相互依赖,配置中心工程创建也很简单,我们新建一个工程,叫com.config
创建启动类如下:@EnableConfigServer注解是声明当前工程是配置中心
1 import org.springframework.boot.SpringApplication; 2 import org.springframework.boot.autoconfigure.SpringBootApplication; 3 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 4 import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; 5 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; 6 import org.springframework.cloud.config.server.EnableConfigServer; 7 8 @SpringBootApplication
9 @EnableConfigServer 10 public class ConfigStart { 11 public static void main(String[] args) { 12 SpringApplication.run(ConfigStart.class, args); 13 } 14 }
application.yml文件如下
1 server: 2 port: 8001 3 spring: 4 application: 5 name: config 6 profiles: 7 active: native # native:启动从本地读取配置文件,必须指定active的值,才可以使用本地文件配置模式 8 cloud: 9 config: 10 server: 11 native: 12 searchLocations: classpath:config # 自定义配置文件路径
application.yml文件中指定了配置文件路径,所以,我们将所有的配置文件放置在自己指定的目录下,如下图:
这些配置文件里面我们主要关心eureka和datasource和login(消费者),eureka里面配置不变,datasource里面配置我们的数据源,最后login(消费者)里面配置如下:
1 server: 2 port: 8085##端口 3 spring: 4 application: 5 name: login 6 profiles: 7 include: eureka,datasource,configure ###依赖的文件
配置也相对简单,当然里面也可以添加一个自己的自定义配置,只不过目前所有的自定义配置都统一放到configure.yml文件中
接下来,我们创建login(消费者),创建工程com.login,创建启动类,@EnableEurekaClient声明这个是一个服务注册的客户端
1 @EnableEurekaClient 2 @SpringBootApplication 3 public class LoginStart { 4 public static void main(String[] args) { 5 SpringApplication.run(LoginStart.class, args); 6 } 7 }
如果我们引入了配置中心服务,那么每个工程下的application.yml文件就不需要了,统一使用配置中心的服务,我们只需要在工程里面去连接配置中心即可,接下来我们看
bootstrap.yml文件如何指向配置中心,application.yml默认使用配置中心里面的文件
1 spring: 2 cloud: 3 # 配置服务器的地址 4 config: 5 uri: http://127.0.0.1:8001 6 # 要读取配置文件读取的值 7 name: login 8 # 如果不设置此值,则系统设置此值为 spring.profiles.active 9 profile: dev 10 # 可以使用之前的版本。默认值可以是git label, branch name or commit id。可以使用多个Label,多个Label可以使用逗号分隔 11 # label: 12 # true: 如果访问配置中心失败,则停止启动服务 13 fail-fast: true 14 # 配置重试,默认是重试6次,最初是延迟1s再次重试,如果再失败,则延迟1.1*1s、1.1*1.1*1s、… 。可以使用这个配置 15 retry: 16 initial-interval: 2000 17 # 最多重试次数 18 max-attempts: 6 19 # 最大重试间隔 20 max-interval: 4000 21 # 每次重试时间是之前的倍数 22 multiplier: 1.2
这样,我们只需要关系配置中心配置文件的配置,对于一些公共配置我们进行统一抽取,然后再配置中心中进行文件依赖,这样我们就不需将同样的配置针对每个服务进行配置,然后启动login服务,查看注册中心如下图:
可以看到,我们刚才创建的消费者已经注册到服务端了,那么问题来了,eureka-server是通过什么来判断当前服务是否可用呢,接下来我们看看eureka的原理和他的自我保护机制以及心跳机制
这是官方网站的架构图,从这个图可以看出是基于集群配置的eureka,Application Service为服务提供者 - Application Client为服务消费者 - Make Remote Call完成一次服务调用
服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN
状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例
2.Eureka的自我保护机制
在默认配置中,Eureka Server在默认90s没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。
为了解决这个问题,Eureka 有自我保护机制,通过在Eureka Server配置如下参数,可启动保护机制
1 eureka.server.enable-self-preservation=true
它的原理是,当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障恢复后,该节点会自动退出自我保护模式。
自我保护模式的架构哲学是宁可放过一千,决不可错杀一个
3. 作为服务注册中心,Eureka比Zookeeper好在哪里
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。
3.1 Zookeeper保证CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
3.2 Eureka保证AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
当网络稳定时,当前实例新的注册信息会被同步到其它节点中
Eureka心跳机制
1.服务器启动成功,等待客户(服务)端注册,在启动过程中如果我们配置了集群,集群之间会同步注册表,每一个Eureka serve都会存在这个集群完整的服务注册表信息
2.Eureka client 启动时根据配置信息,去注册到指定的注册中心
3.Eureka client会每30秒向Eureka server 发送一次心跳请求,证明该客户端服务正常
4.当Eureka server90s内没有接受客户端服务正常,注册中心会认为该节点失效,会注销该实列 (从注册表中删除注册信息)
5.单位时间内如果服务端统计到大量客户端没有发送心跳,则认为网络异常,进去自我保护机制,不在剔除没有发送心跳的客户端
6.当客户端恢复正常之后,服务端就会退出自我保护模式
7.客户端定时全量或增量从注册中心获取服务注册表,并且会缓存到本地
8.服务调用时,客户端会先从本地缓存找到调用服务,如果调取不到 先从注册中心刷新注册表,在同步到本地
9.客户端获取不到目标服务器信息发起服务调用
10.客户端程序关闭时向服务端发送取消请求,服务器将实例从注册表中删除
以上是关于SpringCloud核心组件之---Eureka的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud - Spring Cloud Netflix 之 Eureka 控制台界面详解
广州springcloudの核心组件EurekaRibbonFeignHystrix...
微服务架构SpringCloud之Eureka(服务注册和服务发现基础篇)