1.服务注册和发现的原理
EurekaServer启动的时候注册自己的IP端口服务名称等信息
EurekaClient作为java客户端,在服务启动后周期性的(默认30s)向EurekaServer发送心跳
EurekaServer在一定时间(默认90s)没有收到某个服务的心跳就会注销该实例,EurekaClient发送canel命令后也会注销该实例
EurekaServer之间会相互复制注册表信息
EurekaClient会缓存注册表信息
服务注册与发现
比如现在我们有一个服务消费者 服务A,和两个节点的服务提供者,服务B。服务A 和服务B 在启动的时候都会向注册中心进行服务注册。
服务A 也会定时从服务注册中心定时去拉取服务注册表信息到本地来,这个过程叫服务发现,默认是30S 一次,当然了可以自己去配置。
如下图:
实际上当服务在拉取服务注册表的时候,其实客户端不是直接从 Eureka 中的 服务注册表中获取数据的。
Eureka 做了二级缓存,第一级叫做 ReadOnly 缓存,二级叫做 ReadWrite 缓存。
客户端会直接从ReadOnly 缓存中读取注册表信息。
当服务在进行注册的时候,先往服务注册表中写入注册信息,服务注册表更新了,立马会同步一份数据到 ReadWrite 缓存中去。
那什么时候 ReadWrite 缓存中的数据会到 ReadOnly 缓存中去?
此时有一个定时任务会定时去检查 ReadWrite 是否跟 ReadOnly 不一致,不一致就把数据同步到 ReadOnly 中去。
这个定时任务也默认是 30S。也可以自己配置。
二级缓存的好处在于,优化并发读写的冲突。
如果服务进行注册的时候,同时有服务来读去注册表信息,就会存在频繁的读写加锁的操作,写的时候就不能读,导致性能下降,所以我们需要避免大量的读写都去操作一个表。
那么有了这两层,其实大部分的读操作都会走 ReadOnly 缓存。只需要定时把 ReadWrite 缓存中的数据写入到 ReadOnly 就好了。
心跳与故障检测
服务注册中心还有一个很重要的功能就是 心跳与故障检查。心跳跟故障检测其实就是为了知道注册上来的这些服务是不是还活着的。
Eureka 还会开启一个定时任务定时去检查心跳,默认也是30秒,**eureka是双模式,这个是定时检查心跳就是一个拉模式去检测心跳,**也可以自己设置。
当出现机器故障没有在约定的时间间隔内上报自己的状态,那么Eureka 就会把这台机器剔除注册表,同时更新到 ReadWrite 缓存中去。如图:
但是把数据从ReadWrite 缓存同步到 ReadOnly 缓存是有时间间隔的。当服务消费者A 也只有等待下一次请求更新的时候才会把自己列表里面的服务给更新掉。
所以有时候会出现你注册上去的服务经过及时秒才被服务消费者发现,或者服务的某个节点出现故障,没有及时剔除掉。这里就是同步机制的时间差问题。
以上就是 Eureka 的核心运行原理了。
2.Eureka的两大主体:EurekaServer和EurekaClient
EurekaServer:
提供服务注册,服务信息提供,服务管理(通过Eureka Client的Cancel、心跳监控、renew等方式来维护该服务提供的信息以确保该服务可用以及服务的更新。)
EurekaServer之间的信息同步:
每个Eureka Server同时也是Eureka Client,多个Eureka Server之间通过P2P复制的方式完成服务注册表的同步。同步时,被同步信息不会同步出去。也就是说有3个Eureka Server,Server1有新的服务信息时,同步到Server2后,Server2和Server3同步时,Server2不会把从Server1那里同步到的信息同步给Server3,只能由Server1自己同步给Server3。
EurekaClient:
Eureka Client会拉取、更新和缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者。
Eureka Client在微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒)以续约自己的信息。如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒)。
其它动作:
Register:服务注册
当Eureka客户端向Eureka Server注册时,它提供自身的元数据,比如IP地址、端口,运行状况指示符URL,主页等。
Renew:服务续约
Eureka Client会每隔30秒发送一次心跳来续约。 通过续约来告知Eureka Server该Eureka客户仍然存在,没有出现问题。 正常情况下,如果Eureka Server在90秒没有收到Eureka客户的续约,它会将实例从其注册表中删除。 建议不要更改续约间隔。
Fetch Registries:获取注册列表信息
Eureka客户端从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与Eureka客户端的缓存信息不同, Eureka客户端自动处理。如果由于某种原因导致注册列表信息不能及时匹配,Eureka客户端则会重新获取整个注册表信息。 Eureka服务器缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka客户端和Eureka 服务器可以使用JSON / XML格式进行通讯。在默认的情况下Eureka客户端使用压缩JSON格式来获取注册列表的信息。
Cancel:服务下线
Eureka客户端在程序关闭时向Eureka服务器发送取消请求。 发送请求后,该客户端实例信息将从服务器的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:DiscoveryManager.getInstance().shutdownComponent();
Eviction 服务剔除
在默认的情况下,当Eureka客户端连续90秒没有向Eureka服务器发送服务续约,即心跳,Eureka服务器会将该服务实例从服务注册列表删除,即服务剔除。