哥妞 海淀山后有哥妞

Nacos源码之二—接口读取配置

2021-05-20

Nacos 是阿里巴巴开源的集分布式配置中心、分布式注册中心为一体的分布式解决方案。

它的优点:

  1. 提供命令空间,方便管理不同环境的配置;
  2. 提供web界面,方便管理配置和服务;
  3. 支持配置版本管理,回滚;
  4. 支持服务管理,手动上线、下线服务。

等等其他优点。

读取配置流程

读取配置信息流程图

1、入口在ConfigController::getConfig()方法中;

2、获取读锁,如果获取成功,进行下一步,否则返回失败(小于表示正在写入(写锁),等于0表示没有配置数据,因为读锁可以重复获取);

3、根据groupKey获取缓存中的基础信息(isBeta,configType等信息);

4、根据部署方式(是否standalone)、使用的数据库是否是内置数据库 derby,来判断是否读数据库还是读文件;

5、返回数据库中的content信息(如果是查数据库),或者文件流内容。

需要注意的点

1、如果是standalone部署,并且使用的是内置数据库derby,则直接查询数据库中的数据,cache(ConcurrentHashMap);否则,读取nacos文件系统中(nacos/distribution/target/nacos-server-${version}/nacos/data/config-data/${GROUP_NAME}/${dataId})的数据。

2、获取配置之前,需要获取==读锁==

3、通过ConcurrentHashMap缓存配置文件的基础信息,包括:groupKey,md5,lastModifiedTs

// Determines whether to read the data directly
// if use mysql, Reduce database read pressure
// if use raft+derby, Reduce leader read pressure
public static boolean isDirectRead() {
    return EnvUtil.getStandaloneMode() && isEmbeddedStorage();
}

为什么nacos下线了,还可以获取到配置?

因为服务启动的时候,会访问注册中心nacos,把配置更新到环境变量中,可以打开endpoints

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

然后访问:http://localhost:8080/actuator/env,可以查看到配置数据在环境变量中。

值得学习的地方

读写锁的实现

并没有特别高深的内容,使用synchronized关键字修饰获取锁、释放锁的方法。

读锁可以多次获取,通过int类型的status递增实现多次读锁;

只有一个写锁,标记status为-1。

注意:需要手动释放锁。


/**
 * Simplest read-write lock implementation. Requires locking and unlocking must be called in pairs.
 *
 * @author Nacos
 */
public class SimpleReadWriteLock {
    
    /**
     * Try read lock.
     */
    public synchronized boolean tryReadLock() {
        if (isWriteLocked()) {
            return false;
        } else {
            status++;
            return true;
        }
    }
    
    /**
     * Release the read lock.
     */
    public synchronized void releaseReadLock() {
        status--;
    }
    
    /**
     * Try write lock.
     */
    public synchronized boolean tryWriteLock() {
        if (!isFree()) {
            return false;
        } else {
            status = -1;
            return true;
        }
    }
    
    public synchronized void releaseWriteLock() {
        status = 0;
    }
    
    private boolean isWriteLocked() {
        return status < 0;
    }
    
    private boolean isFree() {
        return status == 0;
    }
    
    /**
     * Zero means no lock; Negative Numbers mean write locks; Positive Numbers mean read locks, and the numeric value
     * represents the number of read locks.
     */
    private int status = 0;
}


1分也是爱


微信扫描二维码,关注公众号 (转载本站文章请注明作者和出处 哥妞-geniu)

Similar Posts

评论