service 對應的概念
用 namespace, group, serviceName 標識一個服務
從該屬性可以看出服務的層級
// Map<namespace, Map<group::serviceName, Service>> com.alibaba.nacos.naming.core.ServiceManager#serviceMap
服務和實例的對應關系
service, cluster, instance
從 2 個方法可以看出實例的層級
// com.alibaba.nacos.naming.core.Service#allIPs() public List<Instance> allIPs() { List<Instance> allIPs = new ArrayList<>(); for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) { allIPs.addAll(entry.getValue().allIPs()); } return allIPs; } // com.alibaba.nacos.naming.core.Cluster#allIPs() public List<Instance> allIPs() { List<Instance> allInstances = new ArrayList<>(); // private Set<Instance> persistentInstances = new HashSet<>(); allInstances.addAll(persistentInstances); // private Set<Instance> ephemeralInstances = new HashSet<>(); allInstances.addAll(ephemeralInstances); return allInstances; }
但是服務還有另外一種扁平的數據結構
以臨時服務為例
DistroConsistencyServiceImpl
DataStore 使用 Map<String, Datum> 存儲 Datum。
Datum 封裝了 key 和 value,實際使用時 value 是 Instances
服務對應一個 key,如下是一個臨時實例的 key:
com.alibaba.nacos.naming.iplist.ephemeral.public##DEFAULT_GROUP@@service-consumer
層級的數據結構響應客戶端請求,扁平的數據結構在 nacos 節點之間用作數據傳輸。
一個 naming 客戶端綁定一個 namespace
@CanDistro 注解
修改服務實例的 Controller method,會打上 CanDistro 注解,表明這個請求由固定節點處理
FilterBase 類,利用發射生成請求 URL 到 Controller Method 的映射:
private ConcurrentMap<String, Method> methodCache = new ConcurrentHashMap<>();
在 DistroFilter.doFilter 中,
1. 根據請求 URL 獲取 Controller Method
2. 如果該 Method 對象有 CanDistro 注解,同時對 group + serviceName 哈希取模,決定處理請求的 nacos 節點
3. 如果當前 service 由其他節點負責,則把請求轉發給其他節點
實例數據保存在本地內存后,產生 2 個異步動作:
1. 推送服務信息給 naming 客戶端,由 Notifier 執行
2. 廣播給集群中的其他節點,由 TaskDispatcher 執行
總結:某個 service 的修改請求由指定的 nacos 節點處理,修改之后數據會同步給其他 nacos 節點。所有的 nacos 節點保存全量的服務元數據。
