注:此随笔为读书笔记。《Spring Cloud微服务实战》,想学习Spring Cloud的同伴们能够去看看此书,里面对源码有详细的解读。缓存
上篇主要介绍了什么是微服务以及微服务治理的简单实现,如微服务注册中心的实现、微服务注册的实现、微服务的发现和消费的实现、微服务注册高可用的实现。本篇主要介绍一下微服务治理机制。服务治理基础架构有是三个核心要素:服务注册中心、服务提供者、服务消费者,服务提供者通常执行服务注册、服务同步、服务续约任务,服务消费者会执行获取服务、服务调用、服务下线任务,服务注册中心会执行失效剔除、自我保护任务。下面一一理解。网络
场景:架构
有两个服务注册中心,互相注册组成高可用集群;负载均衡
服务提供者启动两个实例,一个注册在注册中心1中,一个注册在注册中心2中;(疑问:这里我试了,服务只指向一个注册中心,只启动一个实例,两个注册中心都会有刚启动的服务,这应该也算服务同步吧)微服务
有两个服务消费者,一个指向注册中心1中,一个指向注册中心2中。性能
服务提供者在启动的时候会发送REST请求将本身注册到注册中心,同时带上了自身服务的一些元数据信息。注册中心接收到请求后,将元数据信息存储在一个双层结构Map中,其中第一层的Key是服务名,第二层的Key是具体服务的实例名。如Ribbon负载均衡的例子中,一个服务有多个实例的状况。学习
因为服务注册中心之间互相注册为服务,当服务提供者发送注册请求到其中一个注册中心时,它会将请求转发给集群中相连的其余注册中心,此时集群中全部的注册中心都会注册该服务实例,从而实现注册中心之间的服务同步。经过服务同步,消费者就能够经过这两个注册中心的任意一个获取到两个服务提供者的服务信息。fetch
解释:哪些服务是被服务A同步的呢?spa
即各个注册中心中和服务A的服务名、端口号都相同的服务。debug
注册中心1:
注册中心2:
在服务注册完以后,服务提供者会维护一个心跳来告诉注册中心本身还活着,以防止注册中心的“剔除任务”将该服务实例从服务列表剔除,咱们把该操做称为续约。
eureka.instance.lease-renewal-interval-in-seconds=30 #服务续约任务的调用间隔时间,默认为30秒
eureka.instance.lease-expiration-duration-in-seconds=90 #定义服务失效的时间,默认90秒
到这里,服务注册中心都注册了一个服务,而且该服务都拥有两个服务实例。当咱们启动服务消费者的时候,会发送REST请求给注册中心,来获取注册中心的服务清单。为了性能考虑,注册中心会维护一份只读的服务清单返回给客户端,该缓存清单默认30秒更新一次。
eureka.client.fetch-register=true #肯定会获取注册中心的服务清单
eureka.client.fetch-register-interval-seconds=30 #缓存清单的更新时间,默认30秒
服务消费者获取到服务清单后,经过服务名能够得到服务提供的服务实例名和该实例的元数据信息,因为服务实例有详细的元数据信息,于是客户端能够根据本身的须要调用哪一个服务实例,在Spring Cloud Ribbon中采用轮询的方式进行调用,从而实现客户端的负载均衡。
当服务挂掉后,会触发下线的REST请求给注册中心,注册中心收到请求后会将该服务的状态设置成“DOWN”,并把下线事件传播出去。
有些时候咱们的服务不会正常下线,有多是内存溢出、网络故障等缘由致使服务不可用,而注册中心并外收到服务下线请求。为了从服务列表中将没法提供的服务正确剔除,注册中心在启动的时候会建立一个定时任务,每隔一段时间(默认60秒)将当前服务清单中超时(默认90秒)没有续约的服务剔除。
服务注册到注册中心后,会维护一个心跳链接,告诉注册中心本身还活着。注册中心在运行期间,会统计该服务心跳失败的比例,15分钟低于85%(在开发环境,debug调试的时候很容易出现;生成环境网络不稳定会致使) 的状况下,注册中心会将服务信息保存起来,让这些服务实例不会过时,更不会剔除服务实例。可是这段时间服务实例若出现问题,那么消费者很容易拿到不可用的服务实例,从而出现调用失败的状况。因此客户端须要有容错机制,好比使用请求重试、断路由等机制。
咱们公司内部产品遇到过这种状况,用户登陆系统时有时候超时最终返回错误页面,有时候就能够正常登陆。当时肯定的影响因素是网络很是不稳定,那么在网络稳定性问题解决以前,服务须要正常访问,当时采用的方案是请求重试机制,通常在第二次请求时便会请求成功,并且速度和网络良好的状况差很少。qa那边也会认为这个问题解决了。固然,网络正常后,服务也会正常访问。如今看来,原来是注册中心的自我保护机制致使的。解决方案就是请求重试和断路由等机制了。
因为在本地开发的时候,debug调试,会常常引发注册中心自我保护机制,因此,在本地开发的时候能够关闭注册中心的自我保护机制,以确保注册中心将不可用的服务当即剔除。
eureka.server.enable-self-preservation=false #关闭自我保护机制