SpringCloud服务治理

    在体验了 Spring Cloud Eureka 通过简单的注解配置就能实现强大的服务治理功能之后,我们来进一步了解一下 Eureka 基础架构中各个元素的一些通信行为,以此来理解基于 Eureka 实现的服务治理体系是如何运作起来的。

服务提供者:

    服务注册

    “服务提供者”在启动的时候会通过发送 REST 请求的方式将自己注册到 Eureka Server 上,同时带上了自身服务的一些元数据信息。 Eureka Server 接收到这个 REST 请求之后,将元数据信息存储在一个双层结构 Map其第一层的 key 是服务名,第二层的 key 是具体服务的实例名。(之前在实现 Ribbon 负载均衡的例子中, Eureka 信息面板上一个服务有多个实例的情况,这些内容就是以这样的双层 Map 形式存储的。)

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

    服务同步

    在两个服务提供者分别注册到了两个不同的服务注册中心上,也就是说,它们的信息分别被两个服务注册中心所维护。此时,由于服务注册中心之间因互相注册为服务, 当服务提供者发送注册请求到一个服务注册中心时,它会将该请求转发给集群中相连的其他注册中心,从而实现注册中心之间的服务同步。通过服务同步,两个服务提供者的服务信息就可以通过这两台服务注册中心中任意一台获取到。

    服务续约

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

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

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

扫描二维码关注公众号,回复: 2179311 查看本文章

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

    eureka.instance.lease-renewal-interval-in-seconds 参数用于定义服务续约任务的调用间隔时间,默认为30秒。 

    eureka.instance.lease-expireation-duration-in-seconds 参数用于定义服务失效的时间,默认为90秒。


服务消费者:

    获取服务

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

    获取服务是服务消费者的基础,所以必须保证 eureka.client.fetch-registery=true 参数没有被修改成 false, 该值默认为true。若希望修改缓存清单的更新时间,可以通过 eureka.client.registry-fetch-interval-secondes=30 参数进行修改,该参数默认值为30秒。

    服务调用

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

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

    服务下线

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


服务注册中心

    失效剔除

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

    自我保护

    在我们本地调试基于 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 自己还活着。 Eureka Server 在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server 会将当前的实例注册信息保护起来,让这些实例不会过期,尽可能保护这些注册信息。但是,在这段保护期内实例若是出现问题,那么客户端很容易拿到实际已经不存在的服务实例,会出现调用失败的情况,所以客户端必须要有容错机制,比如可以使用请求重试、断路器等机制。

    由于本地调试很容易触发注册中心的保护机制,这会使得注册中心维护的服务实例不那么准确。 所以,我们在本地进行开发的时候,可以使用 eureka.server.enable-self-preservation=false 参数来关闭保护机制,以确保注册中心将不可用的实例正确剔除。

猜你喜欢

转载自blog.csdn.net/qq1105515654/article/details/80175483