【SpringCloud微服务】第3章 服务治理SpringCloudEureka(四)——Eureka详解

2.7.1 基础架构

服务注册中心Eureka提供的服务端,提供服务注册与发现功能,也就是上一节总我们实现的eureka-server

服务提供者:提供服务的应用,可以是Spring Boot应用,也可以是其他技术平台且遵循eureka通信机制的应用。它将自己提供的服务注册到Eureka,以供其他应用发现,也就是上一节总我们实现的Hello-service

服务消费者:消费者应用从服务注册中心中获取服务列表,从而使消费者可以知道去何处调用其所需要的服务,在上一节中使用了Ribbon来实现服务消费,另外后续还会介绍使用Feign的消费方式。

注意:很多时候,客户端即是服务提供者也是服务消费者

2.7.2 服务治理机制

Eureka实现的服务治理体系是如何运作起来的,其中有这样几个重要的元素:

①“服务注册中心-1”和“服务注册中心-2”, 它们互相注册组成了高可用集群。

②“服务提供者”启动了两个实例,一 个注册到“服务注册中心-1”上, 另外一个注册到“服务注册中 心-2”上。

③还有两个“服务消费者”,它们也都分别只指向了一个注册中心。

 

根据上面的结构,我们详细了解一下,从服务注册开始,到服务调用,各个元素所涉及到的一些重要通信行为:

2.7.3 服务提供者

1.服务注册

①服务提供者在启动的时候会通过发送REST请求的方式将自己注册到EurekaServer上, 同时带上了自身服务的一些元数据信息

Eureka Server接收到这个REST请求之后,将元数据信息存储在一个双层结构Map中, 其中第一层的key是服务名, 第二层的key是具体服务的实例名(我们可以回想一下之前在实现Ribbon负载均衡的例子中, Eureka信息面板中一个服务有多个实例的清况, 这些内容就是以这样的双层Map形式存储的)。

③在服务注册时,需要确认一下 eureka.client.register-with-eureka = true参数是否正确, 该值默认为true。 若设置为false将不会启动注册操作。

2.服务同步

①如架构图中所示,这里的两个服务提供者分别注册到了两个不同的服务注册中心上,也就是说,它们的信息分别被两个服务注册中心所维护。

②由于服务注册中心之间因互相注册为服务,当服务提供者发送注册请求到一个服务注册中心时,它会将该请求转发给集群中相连的其他注册中心,从而实现注册中心之间的服务同步。

③通过服务同步,两个服务提供者的服务信息就可以通过这两台服务注册中心中的任意一台获取到。

3.服务续约

①在注册完成服务之后,服务提供者会维护一个心跳用来持续告诉Eureka Server:我还活着,防止Eureka Server的剔除任务将该服务从服务列表中排除出去,我们称该操作作为服务续约。

②关于续约有两个重要的属性,我们可以关注并根据需要进行调整:

//参数用于定义服务续约任务的调用间隔时间,默认30秒。

eureka.instance.lease-renewal-interval-in-seconds=30

//参数用于定义服务失效的时间,默认90

eureka.instance.lease-expiration-duration-in-seconds=90

2.7.4 服务消费者

1.获取服务

①如图,在服务注册中心已经注册了一个服务,并且该服务有两个实例,当我们启动服务消费者的时候,它会发送一个REST请求给服务注册中心,来获取上面注册的服务清单,为了性能考虑,Eureka Server会维护一份只读的服务清单来返回给客户端,同时该缓存清单会隔30秒更新一次

②获取服务是服务消费者的基础,确保以下参数没有被改成false,默认为true

eureka.client.fetch-registry=true

③可修改缓存清单的更新时间,默认值为30

eureka.client.registry-fetch-interval-seconds = 30

2.服务调用

①服务消费者在获取服务清单后,通过服务名可以获得具体提供服务的实例名和该实例的元数据,因为有这些服务实例的详细信息,所以客户端可以根据自己的需要决定具体调用哪个实例,Ribbon中会默认采用轮询的方式进行调用,从而实现客户端的负载均衡。

②对于访问实例的选择,EurekaRegionZone的概念,一个Region中可以包含多个Zone,每个服务客户端需要被注册到一个Zone中,所以每个客户端对应一个Region和一个Zone,在服务调用的时候,先访问同处一个Zone中的服务提供方,若访问不到,就访问其他的Zone

3.服务下线

在系统运行过程中必然会面临关闭和重启服务的某个实例的情况,在服务关闭期间,我们自然不会希望客户端继续调用关闭了的实例,所以在客户端程序中,当服务实例进行正常的关闭操作时,,会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:我要下线了。服务端在接收到请求后,将该服务状态置为下线(DOWN),并把该下线事件传播出去。

2.7.5 服务注册中心

1.失效剔除

有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障等原因使得服务不能正常工作,而服务注册中心并未收到“服务下线”的请求。为了从服务列表中将这些无法提供服务的实例剔除, EurekaServer在启动的时候会创建一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除出去

2.自我保护

①现象:当我们在本地调试基于Eureka的程序时, 基本上都会碰到这样一个问题, 在服务注册中心的信息面板中出现类似下面的红色警告信息:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEYRE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUSTTO BE SAFE.

实际上,该警告就是触发了EurekaServer自我保护机制

②原因:

a)服务注册到EurekaServer之后,会维护一个心跳连接,告诉EurekaServer自己还活着。EurekaServer在运行期间,会统计心跳失败的比例,在15分钟之内是否低于85%

b)一旦出现低于的情况 (在单机调试的时候很容易满足),Eureka Server会将当前的实例注册信息保护起来,让这些实例不会过期,尽可能保护这些注册信息。

c)但是在这段保护期间内实例若出现问题,那么客户端很容易拿到实际已经不存在的服务实例,会出现调用失败的清况,所以客户端必须要有容错机制,比如可以使用请求重试、断路器等机制。

d)由于本地调试很容易触发注册中心的保护机制,这会使得注册中心维护的服务实例不那么准确。本地进行开发的时候,可关闭保护机制:

eureka.server .enable­-self-preservation= false





猜你喜欢

转载自blog.csdn.net/qq296398300/article/details/79878168