nacos的服务发现详解

简介: nacos的服务发现详解

一,nacos的服务发现

上一篇主要是讲解了这个nacos的服务注册,接下来主要讲讲这个nacos的服务发现。

1,nacos服务发现概述

就是说每个客户端都会去这个服务注册中心里面拉取这个注册表里面的全部实例,最后将这个实例存储在这个客户端的本地缓存里面。

2,nacos服务发现源码分析

2.1,客户端源码分析

在这个NacosNamingService类里面,主要有一个方法getAllInstances方法,主要是获取注册表里里面的所有的实例的信息。最后通过一个list集合将这个全部的实例信息返回。

@Override
public List<Instance> getAllInstances(String sn, String gn, List<String> clusters,boolean subscribe) throws NacosException { 
    ServiceInfo serviceInfo;
    if (subscribe) {
        //获取服务信息
      serviceInfo = hostReactor.getServiceInfo(
            NamingUtils.getGroupedName(sn, gn),StringUtils.join(clusters, ","));
    }else {
       serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(
           NamingUtils.getGroupedName(sn,gn),StringUtils.join(clusters,","));
    }
    List<Instance> list;
    if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
        return new ArrayList<Instance>();
    }
    return list;
}

客户端主要通过这个getServiceInfo方法来查看实例的信息,在这个方法中,主要有以下的代码。首先会判断是否第一次拉取注册中心的全部实例,如果是的话就会去拉取这个注册中心里面的全部数据。然后的话客户端会开启一个定时任务,每隔几秒就会去拉取一次这个注册中心里面的全部实例,然后存放在本地的缓存里面。

public ServiceInfo getServiceInfo(final String serviceName, final String clusters){
    //获取服务的信息
    ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);
    //客户端第一次获取这个注册表信息为空
    if (null == serviceObj) {
        serviceObj = new ServiceInfo(serviceName, clusters);
        serviceInfoMap.put(serviceObj.getKey(), serviceObj);
        updatingMap.put(serviceName, new Object());
        //会去拉取这个注册中心里面的注册表信息
        updateServiceNow(serviceName, clusters);
        updatingMap.remove(serviceName);
    }
    //如果本地缓存里面已有这个注册表信息
    else if (updatingMap.containsKey(serviceName)) {    
       if (UPDATE_HOLD_INTERVAL > 0) {
           synchronized (serviceObj) {
               try {
                   serviceObj.wait(UPDATE_HOLD_INTERVAL);
               } catch (InterruptedException e) {
               }
           }
       }
    }
    //客户端会开启一个定时任务,每隔几秒会去拉取注册中心里面的全部实例的信息
    scheduleUpdateIfAbsent(serviceName, clusters);
  return serviceInfoMap.get(serviceObj.getKey());
}

第一次拉取这个注册中心里面的全部实例主要通过这个updateServiceNow方法实现,里面有一个queryList方法,如下。最终会通过这个reqApi的这个方法,向这个服务的注册中心发起http请求建立连接,最后会拉取服务注册中心里面的全部的这个实例的信息。

public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly) throws NacosException {        
    final Map<String, String> params = new HashMap<String, String>(8);
    params.put(CommonParams.NAMESPACE_ID, namespaceId);
    params.put(CommonParams.SERVICE_NAME, serviceName);
    params.put("clusters", clusters);
    params.put("udpPort", String.valueOf(udpPort));
    params.put("clientIP", NetUtils.localIP());
    params.put("healthyOnly", String.valueOf(healthyOnly));
    //获取服务注册中心里面的全部实例
    return reqApi(UtilAndComs.nacosUrlBase + "/instance/list", params, HttpMethod.GET);
}

2.2,服务端中获取全部实例

由于整个nacos是一个web的服务应用,因此可以在这个instanceContoller类里面查看到这个客户端获取全部服务端里面的实例的请求。这个需要下载nacos的源码,主要是使用nacos的1.4.1的版本。在这个list方法里面,有一个doSrvIpxt方法

@GetMapping("/list")
@Secured(parser = NamingResourceParser.class, action = ActionTypes.READ)
public ObjectNode list(HttpServletRequest request) throws Exception {
    String namespaceId = WebUtils.optional(request,CommonParams.NAMESPACE_ID,Constants.DEFAULT_NAMESPACE_ID);
    String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
    NamingUtils.checkServiceNameFormat(serviceName);
    String agent = WebUtils.getUserAgent(request);
    String clusters = WebUtils.optional(request, "clusters", StringUtils.EMPTY);
    String clientIP = WebUtils.optional(request, "clientIP", StringUtils.EMPTY);
    int udpPort = Integer.parseInt(WebUtils.optional(request, "udpPort", "0"));
    String env = WebUtils.optional(request, "env", StringUtils.EMPTY);
    boolean isCheck = Boolean.parseBoolean(WebUtils.optional(request, "isCheck", "false"));
    String app = WebUtils.optional(request, "app", StringUtils.EMPTY);
    String tenant = WebUtils.optional(request, "tid", StringUtils.EMPTY);
    boolean healthyOnly = Boolean.parseBoolean(WebUtils.optional(request, "healthyOnly", "false"));
    return doSrvIpxt(namespaceId, serviceName, agent, clusters, clientIP, udpPort, env, isCheck, app, tenant, healthyOnly);
}

在这个doSrvIpxt方法里面,会有一个获取所有服务的实例

Service service = serviceManager.getService(namespaceId, serviceName);
//获取所有服务的实例
srvedIPs = service.srvIPs(Arrays.asList(StringUtils.split(clusters, ",")));

然后通过这个srvIPs方法获取所有的实例

public List<Instance> srvIPs(List<String> clusters) {
    if (CollectionUtils.isEmpty(clusters)) {
        clusters = new ArrayList<>();
        clusters.addAll(clusterMap.keySet());
    }
    return allIPs(clusters);
}

最后调用这个allIPs方法来对所有实例进行一个获取

public List<Instance> allIPs(List<String> clusters) {
    List<Instance> result = new ArrayList<>();
    for (String cluster : clusters) {
        Cluster clusterObj = clusterMap.get(cluster);
        if (clusterObj == null) {
            continue;
        }
        //将所有的实例全部添加
        result.addAll(clusterObj.allIPs());
    }
    //将获取的实例返回
    return result;
}

全部的实例通过这个addAll方法将实例全部添加,里面包括了这个持久化实例和临时实例。这样的话就成功获取到了服务端的全部实例

public List<Instance> allIPs() {
    List<Instance> allInstances = new ArrayList<>();
    //持久化实例,对应的ap架构
    allInstances.addAll(persistentInstances);
    //临时实例,对应的ap架构
    allInstances.addAll(ephemeralInstances);
    return allInstances;
}

二,总结

在进行服务注册之后,该服务就会去这个服务注册中心里面拉取全部的微服务实例,会将全部的实例存在本地的缓存里面,并且同时会去开启一个定时任务,每隔几秒就会去拉取一次最新的微服务实例。

相关文章
|
7月前
|
存储 负载均衡 网络协议
看完就会使用Nacos-服务发现
看完就会使用Nacos-服务发现
73 0
|
3月前
|
负载均衡 定位技术 Nacos
Nacos 高级玩法:深入探讨分布式配置和服务发现
Nacos 高级玩法:深入探讨分布式配置和服务发现
372 0
|
3月前
|
负载均衡 网络协议 数据管理
深入解析Nacos:服务发现、配置管理与更多特性解析
深入解析Nacos:服务发现、配置管理与更多特性解析
127 0
|
4月前
|
负载均衡 Java Nacos
Nacos作为一个服务发现与配置管理工具,它本身不直接依赖于`ribbon-loadbalancer`包
Nacos作为一个服务发现与配置管理工具,它本身不直接依赖于`ribbon-loadbalancer`包【1月更文挑战第18天】【1月更文挑战第89篇】
32 4
|
4月前
|
Java 数据库连接 Nacos
Nacos作为一个服务发现和配置管理平台
Nacos作为一个服务发现和配置管理平台【1月更文挑战第18天】【1月更文挑战第88篇】
33 4
|
5月前
|
Linux Nacos 数据库
Linux 通过 Docker 部署 Nacos 2.2.3 服务发现与配置中心
Linux 通过 Docker 部署 Nacos 2.2.3 服务发现与配置中心
|
6月前
|
API Nacos 开发工具
吐槽下Nacos服务发现
吐槽下Nacos服务发现
32 0
|
6月前
|
NoSQL API Nacos
Nacos是一个开源的微服务架构下的服务发现和配置管理工具,
Nacos是一个开源的微服务架构下的服务发现和配置管理工具,
57 2
|
9月前
|
网络协议 Nacos 数据中心
Nacos:服务发现与配置管理利器
在现代分布式系统中,服务的动态发现和配置管理变得越来越重要。Nacos(发音为 "na-kos",中文名:诺克斯)作为一个开源的服务发现和配置管理平台,在这个领域发挥着重要作用。本文将介绍Nacos的基本概念、特性以及在构建可靠分布式系统中的应用。
228 0
|
10月前
|
缓存 SpringCloudAlibaba 负载均衡
springCloudAlibaba组件-Nacos-服务发现与负载均衡(三)
springCloudAlibaba组件-Nacos-服务发现与负载均衡(三)