Spring Cloud微服务技术栈(三):服务治理Spring Cloud Eureka核心元素分析

上一篇文章《Spring Cloud微服务技术栈(二):搭建高可用Eureka Server、服务注册与发现》主要是从使用的角度介绍了Spring Cloud Eureka,包括Eureka服务注册中心的搭建、多服务实例的注册以及服务的发现与消费。本文将继续深入了解Spring Cloud Eureka,将服务治理的核心元素进行简要分析,以帮助我们更加灵活地使用Spring Cloud Eureka

服务治理的核心元素

通过前面的文章的了解,我们知道Eureka服务治理包含了服务注册中心、服务提供者和服务消费者三个核心元素,三者的基本关系是:服务注册中心提供服务注册和服务发现平台,服务提供者将服务注册到服务注册中心,服务消费者从服务注册中心获取服务实例列表并调用。下图展示了三者之间的关系:
Spring Cloud微服务技术栈(三):服务治理Spring Cloud Eureka核心元素分析_第1张图片
现在根据上图来重点说明三个核心元素之间的通信关系:

服务提供者
  • 服务注册

服务提供者启动的时候,会通过发送REST请求方式将自己注册到指定的服务注册中心,注册地址是根据配置文件中配置的eureka.client.service-url.defaultZone来指定的,在请求过程中,携带了一些自身的一些元数据信息,这些元数据信息被Eureka Server接收到以后被存储在一个ConcurrentHashMap中,这个Map是一个双层结构的Map,第一层的key是服务名,第二层的key是实例名。当然,整个注册的前提是配置了eureka.client.register-with-eureka=true(默认值,不配置则为true),如果配置为false,则不会发生注册行为。

  • 服务同步

如上图所示,两个服务提供者分别注册到了不同的服务注册中心,但是两个服务注册中心做了互相注册,形成了集群,当其中的任何一个服务注册中心接收到了服务提供者的注册请求后,就会将请求转发到集群中其他的服务注册中心,这样,集群中其他服务注册中心也维护了服务提供者的服务实例清单,从而实现了服务的同步。

  • 服务续约

服务提供者将自己注册到服务注册中心之后并不是一劳永逸,而是还会周期性地向服务注册中心发送信息,告诉服务注册中心:“我还活着”。也就是服务提供者会维护一个心跳,周期性地和服务注册中心交互,这样做的好处是防止服务注册中心将服务提供者作为一个不可用服务剔除出去,这个周期性地心跳服务通常称之为服务续约。关于服务续约操作,还有两个重要配置:

eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90

第一个配置leaseRenewalIntervalInSeconds,表示服务提供者发送心跳给服务注册中心的频率,既30秒发送一次。如果在leaseExpirationDurationInSeconds后,服务注册中心没有收到服务提供者的心跳,则将剔除该服务(多个实例的情况下剔除某个实例),默认时间是30秒。
第二个配置leaseExpirationDurationInSeconds,表示服务注册中心至上一次收到服务提供者的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将剔除该服务(多个实例的情况下剔除某个实例),默认时间是90秒。

服务消费者
  • 获取服务

假设服务注册中心已经注册了一个服务,且该服务有三个服务实例,当我们启动服务消费者的时候,服务消费者端会发送REST请求到服务注册中心,请求获取已经注册的服务实例清单。为了保证服务的可用性,服务注册中心会和服务提供者以心跳的形式来保证服务的可用性,而服务注册中心和服务消费者之间同样有一份协议,那就是默认每30秒来更新一次服务实例清单给服务消费者,尽可能确保服务的可用性。对于服务实例清单的获取,首先得保证eureka.client.fetch-registry的值为true(默认为true,可以不用配置),如果为false,该消费者将不再从服务注册中心获取服务实例列表。当然,默认的30秒更新服务实例清单缓存也是可以配置的,eureka.client.fetch-registry-interval-seconds的值来配置。

  • 服务调用

服务消费者获取到服务实例清单以后,就可以通过服务提供者的名称来获取服务的具体的实例信息,包括具体实例的元数据(如服务名称、实例名称、实例IP、实例端口等),消费者有了这些信息,就可以调用这些实例来完成具体功能。服务的调用一般由Ribbon来完成,它采用默认的轮询算法,实现客户端负载均衡。

  • 服务下线

一般情况下服务下线值得是服务停止提供服务,服务停止提供服务一般有两种情况:第一种是正常下线,服务在下线之前会发送一个REST请求给服务注册中心,告诉服务注册中心,即将停止服务,这时候服务注册中心接收到请求之后会将服务对应的实例标记为DOWN,并将服务下线的通知传播给消费者。第二种情况是非正常下线,一般非正常下线是由于线路中断或者服务所在服务器的断电造成的,这时候服务注册中心并没有收到下线通知,所以在leaseExpirationDurationInSeconds时间段内,在没有收到心跳的情况下,也会将服务对应的实例标记为DOWN,但是在标记之前,服务消费者可能会继续调用服务,但是此时服务并不可用,所以需要在客户端实现容错保护,降低这种不可抗拒因素导致消费者调用失败而带来的灾难。

服务注册中心
  • 失效剔除

失效剔除是服务注册中心对非正常下线的服务实例进行剔除的一种机制,在每隔一段时间(默认是60秒)将实例清单中的超时(默认是90秒)的服务实例清除出去。

  • 自我保护

服务注册中心有一个自我保护的机制,那就是服务注册中心会统计服务的心跳,如果在15分钟内,服务的心跳失败比例是否低于85%,如果出现低于85%的现象,那么服务注册中心会将这些服务实例的注册信息保护起来,让这些服务实例信息不过期,这些被保护起来的服务实例不一定能再次提供服务,所以在客户端需要建立容错机制,否则服务消费者很容易拿到实际已经不存在或者不提供服务的服务实例。表现在服务注册中心面板上都是一串红色的警告信息:

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.enable-self-preservation=false(默认值为true)即可,这样服务注册中心就可以及时将不可用的服务及时剔除。

总结

服务注册中心、服务提供者和服务消费者作为Eureka服务治理的三大核心元素,理清三者之间的关系至关重要。到这里,已经完成了基本的分析,后面的文章将继续分析Spring Cloud Eureka的部分源码,敬请期待。

你可能感兴趣的:(Spring,Cloud,Spring,Cloud微服务技术栈)