简介
本文介绍为什么Eureka挂了,但微服务还能调通。
这个其实是一道面试题:Eureka挂了,微服务还能调通吗?
结论
Eureka挂了,微服务还能调通。但是,如下情况的服务是调不通的:
- Eureka挂了之后启动的新服务
- 服务提供者修改了IP、端口或者方法的定义
实测
这种问题,听别人讲 N 遍,不如自己手动实践一遍记得清楚。
大家可以快速搭建一个 Eureka 服务注册中心,然后搭建一个服务消费者和服务提供者,将两个服务注册到 Eureka 上去,最后在服务消费者上面简单的调用一下服务提供者。
服务调通之后,接下来关闭 Eureka,注意不要关闭服务提供者和服务消费者,关闭之后,继续用服务消费者调用服务提供者,这个时候你会惊奇的发现,服务竟然还能调通!
原因
为什么 Eureka 关闭后服务还能调用呢?我们先来看一张简单的服务调用图:
流程描述:
- Eureka 作为一个服务注册中心启动。
- Provider 和 Consumer 分别作为服务启动,并且注册到 Eureka 上面去。
- Provider :Provider 注册时会告诉 Eureka,我叫 Provider ,我的地址是 xx.xx.xx.xx,我的端口是 xx,我的 xx 是 xx。即:Provider 会将自己的一些元数据信息告诉 eureka
- Consumer :跟Provider 类似。
- Consumer 调用 Provider 的接口
- Consumer 不知道 Provider 的地址是什么,只知道要调用的服务叫 Provider ,于是 Consumer 找到 Eureka,从 Eureka 上查询出来 Provider 的具体地址和端口,这个具体的地址和端口,可能是一个,也可能是多个(集群化部署)。
- Consumer 获取到 Provider 的地址和端口之后,接下来就直接去调用 Provider 了。
从上面流程图中可以看出,一旦 consumer 获取到 Provider 的具体地址,接下来的调用其实就没有 Eureka 什么事了。
所以,一旦 Eureka 挂了,微服务是可以调通的「但是是有前提的」。
这个前提是:Provider 的地址没变!如果 Provider 换了一个 IP 地址或者端口,Consumer 就无法及时感知到这种变化,就会调不通。当 Eureka 没有挂掉的时候,Provider 的 IP 变化这种事情,可以通过 Eureka 让 Consumer 感知到,进而对调用地址作出调整,现在 Eureka 挂了,Consumer 就无法感知了。
相关原理
Eureka 本身可以分为两大部分,Eureka Server 和 Eureka Client。
我们先来看 Eureka Server:
Eureka Server
Eureka Server 主要对外提供了三个功能:
- 服务注册
- 所有的服务都注册到 Eureka Server 上面来,这是 Eureka 基本功能。
- 提供注册表
- 注册表就是所有注册上来服务的一个列表,Eureka 内部通过一个二层缓存机制来维护这个注册表。
- Eureka Client 在调用服务时,需要获取这个注册表。一般来说,这个注册表会缓存下来,如果缓存失效,则直接获取最新的注册表。
- 同步状态
- Eureka Client 通过注册、心跳等机制,和 Eureka Server 同步当前客户端的状态,以便 Eureka Client 能够及时感知到变化。
Eureka Client
服务要注册到 Eureka 上面去,这种注册本身就是一个 HTTP 请求,但是自己手写注册过程的话太过于繁琐,Eureka Client 可以帮助我们简化注册过程。
一般来说,Eureka Client 有这样一些功能:
服务注册
服务提供者将自己注册到服务注册中心(Eureka Server),需要注意,所谓的服务提供者,只是一个业务上的划分,本质上他就是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,他需要提供自身的一些元数据信息,例如 IP 地址、端口、名称、运行状态等等,将来服务消费者获取到的也是这些信息。
获取注册信息
Eureka Client 从 Eureka Server 上获取服务的注册信息,「并将其缓存在本地」,这句是关键。
当 Eureka Client 在需要调用远程服务时,会从该信息中查找远程服务所对应的 IP 地址、端口等信息。Eureka Client 上缓存的服务注册信息会定期更新(30 秒),如果 Eureka Server 返回的注册表信息与本地缓存的注册表信息不同的话,Eureka Client 会自动处理。
这里,也涉及到两个属性:
- 是否允许获取注册表信息:eureka.client.fetch-registry=true。
- Eureka Client 上缓存的服务注册信息,定期更新的时间间隔
- 默认 30 秒,可以通过如下属性自行修改:eureka.client.registry-fetch-interval-seconds=30。
请先
!