SpringCloud学习笔记
问题
1 如果注册中心Nacos宕机,那么服务还能调用另一个服务吗?
假如存在订单服务A、订单服务B、商品服务C,只允许订单服务调用商品服务。
简答:
- 如果服务A在注册中心宕机前调用过服务B,那么服务A就会缓存服务B的url等信息。这时如果Nacos宕机,依然可以通过缓存调用。
- 如果不存在上述缓存,则服务A就找不到服务B的地址,从而导致调用失败。
实验:
- 把所有服务和nacos正常启动,然后访问订单A,发现A可以成功调用商品服务C。
- 关掉nacos,再次访问订单A,订单A依然可以调用商品服务C。
- 访问订单B,发现无法调用订单C。
深究
-
由实验的步骤二和三可以看出,这个缓存似乎把调用者和被调用者绑定了,只有调用者才能使用该缓存?
答:这个缓存是存在于调用者(订单服务A)内部的,并且每个调用者服务实例都维护着自己的一份独立缓存。订单服务A的缓存和订单服务B的缓存是完全隔离的、互不相干的。所以,只有当一个调用者(如订单A)成功从Nacos拉取过某个服务(如商品C)的信息后,它自己的缓存里才会有数据。 -
这个缓存存在哪里?
答:这个缓存就存放在订单服务A这个Java进程的内存里,并且通常也会有对应的本地文件快照作为灾备。它不依赖任何外部组件,是服务发现客户端SDK的一个内置功能。 -
为什么订单A可以调用,而订单B不能调用?
答:因为订单A之前成功调用过商品服务C,所以自己有商品服务C的缓存。订单B没有。而缓存又是隔离的,所以有上述结果。 -
这个缓存保存了哪些信息?
答:这个缓存保存了服务名 (Service Name)、集群名 (Cluster Name)、实例列表 (Hosts/Instances)、最后刷新时间 (lastRefTime)等信息。实例列表是一个数组,包含了该服务所有健康实例的地址和元数据。
一个缓存文件的例子:{"name": "DEFAULT_GROUP@@product-service","clusters": "","lastRefTime": 1678886400000,"hosts": [{"instanceId": "192.168.1.101#8080#DEFAULT#DEFAULT_GROUP@@product-service","ip": "192.168.1.101","port": 8080,"weight": 1.0,"healthy": true,"enabled": true,"ephemeral": true,"clusterName": "DEFAULT","serviceName": "DEFAULT_GROUP@@product-service","metadata": {"preserved.register.source": "SPRING_CLOUD","version": "1.0.2"},"instanceHeartBeatInterval": 5000,"instanceHeartBeatTimeOut": 15000,"ipDeleteTimeout": 30000,"instanceIdGenerator": "simple"},{"instanceId": "192.168.1.102#8080#DEFAULT#DEFAULT_GROUP@@product-service","ip": "192.168.1.102","port": 8080,"weight": 1.0,"healthy": true,"enabled": true,"ephemeral": true,"clusterName": "DEFAULT","serviceName": "DEFAULT_GROUP@@product-service","metadata": {"preserved.register.source": "SPRING_CLOUD","version": "1.0.3"},"instanceHeartBeatInterval": 5000,"instanceHeartBeatTimeOut": 15000,"ipDeleteTimeout": 30000,"instanceIdGenerator": "simple"}],"cacheMillis": 10000,"useSpecifiedURL": false,"checksum": "e5a37213e84381f286b03df52f87d7f1","env": "","dom": "product-service" }
-
这个缓存何时会刷新(缓存一致性问题)?
答:一般有三个场景。
a. 注册中心主动推送
这是最主要、最实时的刷新方式。Nacos 采用了“发布-订阅”模型。触发条件:只要商品服务C的实例列表发生任何变化,例如:有新的商品服务实例上线注册。有商品服务实例正常下线(Deregister)。有商品服务实例因为心跳超时而被服务器标记为不健康。实例的元数据(Metadata)发生了变更。
过程:一旦发生上述变化,Nacos Server 会立即将最新的、完整的商品服务C的实例列表主动推送给所有订阅了该服务的客户端(比如订单服务A和订单服务B)。
b. 客户端(即各个服务)定时拉取 (Pull)
这是一种兜底和校对机制,作为服务器主动推送的补充。触发机制:Nacos 客户端(即各个服务)内部有一个定时任务,会以一个固定的周期(这个周期可以配置,通常是几十秒)向 Nacos Server 发起一次拉取请求,询问它所订阅的服务列表是否有变化。
过程:客户端向服务端请求数据的摘要(checksum),如果服务端的摘要与客户端本地缓存的摘要不一致,说明数据发生了变化,客户端就会拉取最新的全量数据来更新本地缓存。如果摘要一致,则不做任何操作。
c.Nacos Server 从宕机中恢复后
Nacos Server 从宕机中恢复后,缓存会立即进行一次全量同步和刷新。触发条件:Nacos 客户端在后台会有一个重连机制,不断尝试与 Server 建立连接。一旦客户端检测到与 Nacos Server 的连接恢复,它会立即发起一次对自己所有订阅服务的全量拉取请求。这个过程会用从 Server 获取到的最新、最准确的数据来覆盖掉本地的缓存,无论是内存缓存还是磁盘快照。同步完成后,客户端就正常工作模),重新开始接收服务端的实时推送和进行定时拉取。
基础
to be continued