在微服务架构里,注册中心(像 Nacos、Eureka、Consul 等)是服务发现与治理的核心。可要是注册中心突然宕机,微服务间的远程调用还能顺利进行吗?这是面试时很常被问到的问题,下面我们就来深入剖析。
一、远程调用的 “两次请求” 与实例缓存的引入
在没有实例缓存的情况下,微服务每次发起远程调用,大致要经历以下两次请求:
- 请求注册中心,获取目标服务的地址列表:服务消费者得先去注册中心查询,找到自己要调用的服务提供者都有哪些实例,以及这些实例对应的网络地址。
- 向目标服务的具体地址发送请求:拿到地址列表后,消费者会挑选其中一个地址,向对应的服务提供者发送实际的业务请求。
不过,这种每次调用都进行两次请求的方式,会让性能大打折扣。为了解决这个问题,实例缓存就应运而生了。实例缓存的作用是在服务消费者本地,同步并实时更新注册中心里的服务实例信息。有了它,服务消费者不用每次调用都去注册中心查询,能直接从本地缓存里获取目标服务的地址,从而提升调用效率。
二、注册中心宕机时,远程调用能否成功?
注册中心宕机后,远程调用是否能成功,关键要看服务消费者本地有没有目标服务的实例缓存。
场景一:服务消费者已有目标服务的实例缓存
比如 “订单” 服务之前调用过 “商品” 服务,此时 “订单” 服务本地已经缓存了 “商品” 服务的实例地址。
由于实例缓存还存在,“订单” 服务发起远程调用时,就不再依赖注册中心了。它会直接从本地缓存里取出 “商品” 服务的地址,然后发送请求,所以远程调用能成功。
这也体现出实例缓存的重要性,它让微服务在注册中心短暂不可用的时候,依然能保证服务间调用的连续性,增强了系统的容错能力。
场景二:服务消费者无目标服务的实例缓存
要是 “订单” 服务是第一次发起对 “商品” 服务的远程调用,也就是之前从来没有调用过 “商品” 服务,本地没有 “商品” 服务的实例缓存。
这种情况下,“订单” 服务要发起远程调用,就必须依赖注册中心去获取 “商品” 服务的地址列表。但现在注册中心已经宕机,“订单” 服务没办法获取到目标服务的地址,所以远程调用不能成功。
三、总结
注册中心宕机后,远程调用是否能成功,取决于服务消费者本地是否有目标服务的实例缓存:
- 若有缓存(之前调用过目标服务),远程调用能成功,因为可以从本地缓存获取服务地址,不依赖注册中心。
- 若没有缓存(首次调用目标服务),远程调用会失败,因为获取服务地址必须依赖注册中心。
由此可见,实例缓存是微服务架构中提升远程调用性能、增强系统容错性的关键机制,它在注册中心和服务消费者之间,搭建了一道 “缓冲屏障”,让系统在注册中心出现异常时,仍能维持一定程度的服务调用能力。