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,把配置更新到环境变量中,可以打开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源码之——更新配置,近期会重新整理一下发出来,大家可以期待一下。