NACOS 源码小记

目录标题

  • NAME
    • 注册
  • 配置
    • 过程

  • 实例注册 http://127.0.0.1:8848/nacos/v1/ns/instance?app=unknown&groupName=DEFAULT_GROUP&metadata=%7B%7D&namespaceId=quickStart&port=8888&enable=true&healthy=true&clusterName=TEST1&ip=11.11.11.11&weight=1.0&ephemeral=true&serviceName=DEFAULT_GROUP%40%40nacos.test.3
  • 返回实例 http://127.0.0.1:8848/nacos/v1/ns/instance/list?app=unknown&healthyOnly=false&namespaceId=quickStart&clientIP=192.168.42.153&serviceName=DEFAULT_GROUP%40%40nacos.test.3&udpPort=60854&clusters=
  • NAME API 代理 com.alibaba.nacos.client.naming.net.NamingProxy
  • com.alibaba.nacos.client.naming.net.NamingProxy#reqApi(java.lang.String, java.util.Map, java.util.Map, java.util.List, java.lang.String)
  • com.alibaba.nacos.client.naming.net.NamingProxy#callServer(java.lang.String, java.util.Map, java.util.Map, java.lang.String, java.lang.String)

NAME

com.alibaba.nacos.client.naming.net.NamingProxy 主要类

注册

   Properties properties = new Properties();
    properties.setProperty("serverAddr", "127.0.0.1:8848");
    properties.setProperty("namespace", "quickStart");
    NamingService naming = NamingFactory.createNamingService(properties);
    naming.registerInstance("nacos.test.3", "11.11.11.11", 8888, "TEST1");
    naming.registerInstance("nacos.test.3", "2.2.2.2", 9999, "DEFAULT");
    System.out.println(naming.getAllInstances("nacos.test.3"));

NamingService naming = NamingFactory.createNamingService(properties);

 /**
     * Create a new naming service.
     *反射实现
     * @param properties naming service properties
     * @return new naming service
     * @throws NacosException nacos exception
     */
    public static NamingService createNamingService(Properties properties) throws NacosException {
        try {
            Class driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
            Constructor constructor = driverImplClass.getConstructor(Properties.class);
            NamingService vendorImpl = (NamingService) constructor.newInstance(properties);
            return vendorImpl;
        } catch (Throwable e) {
            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
        }
    }

配置

  • 获取配置文件 http://localhost:8848/nacos/v1/cs/configs?dataId=test&group=DEFAULT_GROUP
  • 设置配置文件 http://localhost:8848/nacos/v1/cs/configsPOST
  • 设置配置文件监听器 http://localhost:8848/nacos/v1/cs/configs/listenerPOST [Listening-Configs -> testDEFAULT_GROUP9a0364b9e99bb480dd25e1f0284c8555]
  • 移除配置文件 http://localhost:8848/nacos/v1/cs/configs?dataId=test&group=DEFAULT_GROUPDELETE

过程

反射初始化 ConfigService

    public static ConfigService createConfigService(Properties properties) throws NacosException {
        try {
            Class driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
            Constructor constructor = driverImplClass.getConstructor(Properties.class);
            ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
            return vendorImpl;
        } catch (Throwable e) {
            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
        }
    }

构造函数

  public NacosConfigService(Properties properties) throws NacosException {
        ValidatorUtils.checkInitParam(properties);
        String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);
        if (StringUtils.isBlank(encodeTmp)) {
            this.encode = Constants.ENCODE;
        } else {
            this.encode = encodeTmp.trim();
        }
        initNamespace(properties);
        /**
         * 初始化服务访问代理
         */
        this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
        /**
         * 代理启动
         */
        this.agent.start();
        /**
         * 客户端定时任务
         */
        this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties);
    }
    @SuppressWarnings("PMD.ThreadPoolCreationRule")
    public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager,
            final Properties properties) {
        this.agent = agent;
        this.configFilterChainManager = configFilterChainManager;

        // Initialize the timeout parameter

        init(properties);
        /**
         * 定时任务
         */
        this.executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
                t.setDaemon(true);
                return t;
            }
        });

        this.executorService = Executors
                .newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        Thread t = new Thread(r);
                        t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
                        t.setDaemon(true);
                        return t;
                    }
                });

        this.executor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                try {
                    /**
                     * 定时轮询查询 配置文件信息 10微秒
                     */
                    checkConfigInfo();
                } catch (Throwable e) {
                    LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e);
                }
            }
        }, 1L, 10L, TimeUnit.MILLISECONDS);
    }

    public void checkConfigInfo() {
        // Dispatch taskes.
        int listenerSize = cacheMap.get().size();
        // Round up the longingTaskCount.
        int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
//        新线程查询
        if (longingTaskCount > currentLongingTaskCount) {
            for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
                // The task list is no order.So it maybe has issues when changing.定时轮询 查看配置文件改变
                executorService.execute(new LongPollingRunnable(i));
            }
            currentLongingTaskCount = longingTaskCount;
        }
    }

任务实现

           /**
                 * 从缓存中获取 已监听的配置信息 ,轮询查看是否变换
                 */
                // check failover config
                for (CacheData cacheData : cacheMap.get().values()) {
                    if (cacheData.getTaskId() == taskId) {
                        cacheDatas.add(cacheData);
                        try {
                            checkLocalConfig(cacheData);
                            if (cacheData.isUseLocalConfigInfo()) {
                                cacheData.checkListenerMd5();
                            }
                        } catch (Exception e) {
                            LOGGER.error("get local config info error", e);
                        }
                    }
                }

CacheData

    void checkListenerMd5() {
        /**
         * 检验MD5
         */
        for (ManagerListenerWrap wrap : listeners) {
            if (!md5.equals(wrap.lastCallMd5)) {
                safeNotifyListener(dataId, group, content, type, md5, wrap);
            }
        }
    }
  private void safeNotifyListener(final String dataId, final String group, final String content, final String type,
            final String md5, final ManagerListenerWrap listenerWrap) {
        final Listener listener = listenerWrap.listener;
        /**
         * 新线程通知
         */
        Runnable job = new Runnable() {
            @Override
            public void run() {
                ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader();
                ClassLoader appClassLoader = listener.getClass().getClassLoader();
                try {
                    if (listener instanceof AbstractSharedListener) {
                        AbstractSharedListener adapter = (AbstractSharedListener) listener;
                        adapter.fillContext(dataId, group);
                        LOGGER.info("[{}] [notify-context] dataId={}, group={}, md5={}", name, dataId, group, md5);
                    }
                    // 执行回调之前先将线程classloader设置为具体webapp的classloader,以免回调方法中调用spi接口是出现异常或错用(多应用部署才会有该问题)。
                    Thread.currentThread().setContextClassLoader(appClassLoader);

                    ConfigResponse cr = new ConfigResponse();
                    cr.setDataId(dataId);
                    cr.setGroup(group);
                    cr.setContent(content);
                    configFilterChainManager.doFilter(null, cr);
                    String contentTmp = cr.getContent();
                    //调用监听器监听
                    listener.receiveConfigInfo(contentTmp);

                    // compare lastContent and content
                    if (listener instanceof AbstractConfigChangeListener) {
                        Map data = ConfigChangeHandler.getInstance()
                                .parseChangeData(listenerWrap.lastContent, content, type);
                        ConfigChangeEvent event = new ConfigChangeEvent(data);
                        ((AbstractConfigChangeListener) listener).receiveConfigChange(event);
                        listenerWrap.lastContent = content;
                    }

                    listenerWrap.lastCallMd5 = md5;
                    LOGGER.info("[{}] [notify-ok] dataId={}, group={}, md5={}, listener={} ", name, dataId, group, md5,
                            listener);
                } catch (NacosException ex) {
                    LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}",
                            name, dataId, group, md5, listener, ex.getErrCode(), ex.getErrMsg());
                } catch (Throwable t) {
                    LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} tx={}", name, dataId,
                            group, md5, listener, t.getCause());
                } finally {
                    Thread.currentThread().setContextClassLoader(myClassLoader);
                }
            }
        };

你可能感兴趣的:(Nacos,java)