vlambda博客
学习文章列表

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

读取配置流程

读取配置信息流程图

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-{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源码之三—接口读取配置
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;
}

PS:之前写了一篇关于Nacos源码之——更新配置,近期会重新整理一下发出来,大家可以期待一下。