SpringCloud详解 第一章 服务治理Eureka (二)
在体验了 Spring Cloud Eureka通过简单的注解配置就能实现强大的服务治理功能之 后,我们来进一步了解一下Eureka基础架构中各个元素的一些通信行为,以此来理解基于 Eureka实现的服务治理体系是如何运作起来的。以下图为例,其中有这样几个重要元素:
- “服务注册中心・1”和“服务注册中心・2”,它们互相注册组成了高可用集群。
- “服务提供者”启动了两个实例,一个注册到“服务注册中心-1”上,另外一个注 册到“服务注册中心・2”上。
- 还有两个“服务消费者”,它们也都分别只指向了一个注册中心。
一、服务提供者
1、服务注册
“服务提供者”在启动的时候会通过发送REST请求的方式将自己注册到Eureka Server 上,同时带上了自身服务的一些元数据信息。Eureka Server接收到这个REST请求之后, 将元数据信息存储在一个双层结构Map中,其中第一层的key是服务名,第二层的key是 具体服务的实例名。(我们可以回想一下之前在实现Ribbon负载均衡的例子中,Eureka信 息面板中一个服务有多个实例的情况,这些内容就是以这样的双层Map形式存储的。)
在服务注册时,需要确认一下 eureka. client. register-with-eureka=true 参数是否正确,该值默认为true。若设置为false将不会启动注册操作。
2、服务同步
如架构图中所示,这里的两个服务提供者分别注册到了两个不同的服务注册中心上, 也就是说,它们的信息分别被两个服务注册中心所维护。此时,由于服务注册中心之间因 互相注册为服务,当服务提供者发送注册请求到一个服务注册中心时,它会将该请求转发给集群中相连的其他注册中心,从而实现注册中心之间的服务同步。通过服务同步,两个 服务提供者的服务信息就可以通过这两台服务注册中心中的任意一台获取到。
3、服务续约
在注册完服务之后,服务提供者会维护一个心跳用来持续告诉Eureka Server: "我还活 着”,以防止Eureka Server的“剔除任务”将该服务实例从服务列表中排除岀去,我们称 该操作为服务续约(Renew)。
关于服务续约有两个重要属性,我们可以关注并根据需要来进行调整:
eureka.instance ・lease-renewal-interval-in-seconds=30 eureka•instance.lease-expiration-duration-in-seconds=90
eureka . instance . lease-renewal-interval-in-seconds 参数用于定义月艮 务续约任务的调用间隔时间,默认为30秒。eureka . instance . lease-expiration- duration-in-seconds参数用于定义服务失效的时间,默认为90秒。
二、服务消费者
1、获取服务
到这里,在服务注册中心己经注册了一个服务,并且该服务有两个实例。当我们启动 服务消费者的时候,它会发送一个REST请求给服务注册中心,来获取上面注册的服务清 单。为了性能考虑,Eureka Server会维护一份只读的服务清单来返回给客户端,同时该缓 存清单会每隔30秒更新一次。
获取服务是服务消费者的基础,所以必须确保eureka. client. fetch-registry= true参数没有被修改成false,该值默认为true。若希望修改缓存清单的更新时间,可
以通过 eureka . client. registry-fetch-interval-seconds=30 参数进彳亍修改, 该参数默认值为30,单位为秒。
2、服务调用
服务消费者在获取服务清单后,通过服务名可以获得具体提供服务的实例名和该实例 的元数据信息。因为有这些服务实例的详细信息,所以客户端可以根据自己的需要决定具 体调用哪个实例,在Ribbon中会默认釆用轮询的方式进行调用,从而实现客户端的负载均 衡。
对于访问实例的选择,Eureka中有Region和Zone的概念,一个Region中可以包含多个 Zone,每个服务客户端需要被注册到一个Zone中,所以每个客户端对应一个Region和一个 Zoneo在进行服务调用的时候,优先访问同处一个Zone中的服务提供方,若访问不到,就 访问其他的Zone,
3、服务下线
在系统运行过程中必然会面临关闭或重启服务的某个实例的情况,在服务关闭期间, 我们自然不希望客户端会继续调用关闭了的实例。所以在客户端程序中,当服务实例进行 正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册 中心:“我要下线了”。服务端在接收到请求之后,将该服务状态置为下线(DOWN),并把 该下线事件传播出去。
三、服务注册中心
1、失效剔除
有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障等原 因使得服务不能正常工作,而服务注册中心并未收到“服务下线”的请求。为了从服务列 表中将这些无法提供服务的实例剔除,Eureka Server在启动的时候会创建一个定时任务, 默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔 除出去。
2、自我保护
当我们在本地调试基于Eureka的程序时,基本上都会碰到这样一个问题,在服务注册 中心的信息面板中出现类似下面的红色警告信息:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
实际上,该警告就是触发了 Eureka Server的自我保护机制。之前我们介绍过,服务注 册到Eureka Server之后,会维护一个心跳连接,告诉Eureka Server自己还活着oEureka Server
在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(在 单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka
Server会将当前的实例注册信息保护起来,让这些实例不会过期,尽可能保护这些注册信
息。但是,在这段保护期间内实例若出现问题,那么客户端很容易拿到实际己经不存在的 服务实例,会出现调用失败的情况,所以客户端必须要有容错机制,比如可以使用请求重 试、断路器等机制。
由于本地调试很容易触发注册中心的保护机制,这会使得注册中心维护的服务实例不 那么准确。所以,我们在本地进行开发的时候,可以使用eureka . server . enablesei f-preservat ion=f al se 参数来关闭保护机制,以确保注册中心可以将不可用的实 例正确剔除。